layers drag drope done
@@ -11,6 +11,9 @@
|
|||||||
"start": "next start --port 3333"
|
"start": "next start --port 3333"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.1.0",
|
||||||
|
"@dnd-kit/sortable": "^8.0.0",
|
||||||
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"@headlessui/react": "^1.7.17",
|
"@headlessui/react": "^1.7.17",
|
||||||
"@next-auth/prisma-adapter": "^1.0.7",
|
"@next-auth/prisma-adapter": "^1.0.7",
|
||||||
"@prisma/client": "^5.1.1",
|
"@prisma/client": "^5.1.1",
|
||||||
@@ -38,6 +41,7 @@
|
|||||||
"@trpc/react-query": "^10.37.1",
|
"@trpc/react-query": "^10.37.1",
|
||||||
"@trpc/server": "^10.37.1",
|
"@trpc/server": "^10.37.1",
|
||||||
"@types/uuid": "^9.0.3",
|
"@types/uuid": "^9.0.3",
|
||||||
|
"@uiw/react-color": "^2.0.3",
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.5.1",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
|
|||||||
372
pnpm-lock.yaml
generated
@@ -5,6 +5,15 @@ settings:
|
|||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@dnd-kit/core':
|
||||||
|
specifier: ^6.1.0
|
||||||
|
version: 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@dnd-kit/sortable':
|
||||||
|
specifier: ^8.0.0
|
||||||
|
version: 8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0)
|
||||||
|
'@dnd-kit/utilities':
|
||||||
|
specifier: ^3.2.2
|
||||||
|
version: 3.2.2(react@18.2.0)
|
||||||
'@headlessui/react':
|
'@headlessui/react':
|
||||||
specifier: ^1.7.17
|
specifier: ^1.7.17
|
||||||
version: 1.7.17(react-dom@18.2.0)(react@18.2.0)
|
version: 1.7.17(react-dom@18.2.0)(react@18.2.0)
|
||||||
@@ -86,6 +95,9 @@ dependencies:
|
|||||||
'@types/uuid':
|
'@types/uuid':
|
||||||
specifier: ^9.0.3
|
specifier: ^9.0.3
|
||||||
version: 9.0.6
|
version: 9.0.6
|
||||||
|
'@uiw/react-color':
|
||||||
|
specifier: ^2.0.3
|
||||||
|
version: 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.5.1
|
specifier: ^1.5.1
|
||||||
version: 1.5.1
|
version: 1.5.1
|
||||||
@@ -217,6 +229,49 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime: 0.14.0
|
regenerator-runtime: 0.14.0
|
||||||
|
|
||||||
|
/@dnd-kit/accessibility@3.1.0(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
tslib: 2.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@dnd-kit/core@6.1.0(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
react-dom: '>=16.8.0'
|
||||||
|
dependencies:
|
||||||
|
'@dnd-kit/accessibility': 3.1.0(react@18.2.0)
|
||||||
|
'@dnd-kit/utilities': 3.2.2(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
tslib: 2.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@dnd-kit/core': ^6.1.0
|
||||||
|
react: '>=16.8.0'
|
||||||
|
dependencies:
|
||||||
|
'@dnd-kit/core': 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@dnd-kit/utilities': 3.2.2(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
tslib: 2.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@dnd-kit/utilities@3.2.2(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
tslib: 2.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@eslint-community/eslint-utils@4.4.0(eslint@8.52.0):
|
/@eslint-community/eslint-utils@4.4.0(eslint@8.52.0):
|
||||||
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
|
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@@ -2175,6 +2230,323 @@ packages:
|
|||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@uiw/color-convert@2.0.3(@babel/runtime@7.23.2):
|
||||||
|
resolution: {integrity: sha512-lP/dnZzaiUDMrn3F+WYAG/TLhIanoy5A0HAPEO6Z/s3Jv5AI0nOM2bVOm0HI+vNiHZkVTkE1oGP0k+endEA+9A==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-alpha@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-bTO0jMTT2fFZr8lGpDrOCbMSbidkgYMuCmyc6A8p6WfyCznKZvKG5WG9KukDOB2ReJUZKIaiR20CgUa6opS3Hw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-drag-event-interactive': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-block@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-KDl4PBtv8/IAQ/HeonxsFka+9ppBTjKBhI7U/j6oxqvVPWuvqOZSGlAtr9oIGZnEG14CXZPg4xNVLkZQkfJ8vg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-swatch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-chrome@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-qT9mdTf1wc1zTAb5K2sAs4VtNM9GwcR36ZeCbrLYLRMpovu4ynsZBAn0hR4RYc1xJJsedRZtelWPInAKLvwyEA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-hsla': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-rgba': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-github': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-hue': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-saturation': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-circle@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-IBMzGOSVQvN/x5dAFk2j1bkGzWX/nWz9kmbcdETRhIQtBcP1AmrQHaRL3E+GX7oTB6cRMg2W20baxHgj97NQIQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-swatch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-colorful@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-IjnvYyroW/Kmz1ICSwQ6HUpl7cs6Rkh2mVuFGvYd8FOxBjbQuAI/pfVi8I54rgkesn8uRVYlbvl4ROfAl3RrHw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-hue': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-saturation': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-compact@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-xjPn46zuFZZ0RqEB8ZelSdtU0ySpp4Ekgw+Wu/W7ZZrUGBXypgFSbQqudggOq7ovhU+4qxGOGqrN4SGHqH36mg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-rgba': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-swatch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-editable-input-hsla@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-RwFgPlOv/OjAtegCYIsoIFbWHhAEE44SMT/44zGlRfYq6PX3KvXjEfHpM7F7EFJHYuRfKFpQRhikc1kSkOeWVw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-editable-input-rgba': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-editable-input-rgba@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-ROz25EVr5F9XgNLG9p0RKMTgzg5ORh2RxMKC8Ch3vXrdTt4FL350Kq0N5KMHs7gyQAzcr4GQmuaCLlbEHHYAwA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-editable-input@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-Zy+BuvtQ5c2XcSPN+zgVQ0gnz4fl+1YB1kpKnTYNyZptL2HXWPygwz2OdfNB/bVNRR34s5/4x3jD/zNQTBe60w==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-github@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-pMv6lc76UmReAKtKlNSyHoFTpeeyD4z2Vr51uiiQqHS09wXisyPRX0KvpvWnGtBXXci9dkOx8kpohwhiKGpPHw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-swatch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-hue@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-Bi9/JkLH6FSxULC52y7kjLlunkRbL6TRuAzm5+BBs/4tSf+VL8Xp5Dr2gCPJG1vuA4ohDx9vl3P5QO4Rk9h8wQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-material@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-xgJ76LvF+LM+8emUby1EwcIwdtTLlA0JpQePwZi78J1DY3gQs9tTWHCaAkqZoprHiNlzXTHtqi8Wg/i0MIPLPw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-rgba': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-saturation@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-+AZM3WemWv7w/uRGmSY5lXWdSJoKKysKMW+C7/qkWNQmN/WjG6YmC4ZtcEqPr7BbWFXSS2DJTn15fNBvxCFKDg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-drag-event-interactive': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-shade-slider@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-TTxNkzExgurWKklC90+D1HbtRMD37wKoK9kOLOvLynEm3r5SgcifjvZLNIBC8CUTbQutazAKl1IXgQCST09ang==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-sketch@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-OS7nD7DlsYhtQJrSQOwM2kXcLrpqYzbLcY6dy55odmgMPx1ixbhhgXfDp8zAPOT5+guPAOdfy4PV4fpUGGYiSg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-rgba': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-hue': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-saturation': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-swatch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-slider@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-ejIVLFVwNYGlGqesJOwOgw1DYBljeHB2pznJCQI/YZyVVq9pM/fjDCjpxFQ/BgU7k/Ezs/UW90QHIxOy+tct4g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-swatch@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-xKUASrSB4wPQ+kmMV1Yr1gQ9BZvMzkdotr9o+CYFGvZNSLclEur0cIhu5RkBhZ6PGP6Vd54mod43amY/a905lw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color-wheel@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-IEQ75777ZNvaA2dunTc/zD7OmcwbTjKeLGZ7Mo8ID+Em0rLF7SCC+9g2pF8G468MAc9HwyfRjv8K6Z69PWUyNg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-drag-event-interactive': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-color@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-W2zin6cxq1clQAJoUSbFbp07SkMKtYaoCOK1dLGE0OUM/oYMEw9eXTa8VbvVCY1e3plkXnA+/HgiCFBm6tVsQg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@uiw/color-convert': 2.0.3(@babel/runtime@7.23.2)
|
||||||
|
'@uiw/react-color-alpha': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-block': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-chrome': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-circle': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-colorful': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-compact': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-hsla': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-editable-input-rgba': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-github': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-hue': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-material': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-saturation': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-shade-slider': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-sketch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-slider': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-swatch': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@uiw/react-color-wheel': 2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@uiw/react-drag-event-interactive@2.0.3(@babel/runtime@7.23.2)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-r9VQbvpk2z0ux3GenmT5K4BVQqT91eBSDQjYuR43Ya0kJaD2yJPuPe8JqvKTFR3/C9kldolJoWbxl0mbuu1X0w==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.19.0'
|
||||||
|
react: '>=16.9.0'
|
||||||
|
react-dom: '>=16.9.0'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@ungap/structured-clone@1.2.0:
|
/@ungap/structured-clone@1.2.0:
|
||||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|||||||
11
src/assets/12.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
.st1{font-family:'GaramondThree';}
|
||||||
|
.st2{font-size:16px;}
|
||||||
|
</style>
|
||||||
|
<text transform="matrix(0.4439 0 0 1 283.2148 425.3496)" class="st0 st1 st2">12% vol.</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 575 B |
27
src/assets/FE.svg
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M296.14,421.35c-0.14-0.22-0.71-0.39-0.53-0.4c0.18-0.01,0.53-0.47,0.71-0.56c0.18-0.08,0.21,0,0.45,1.3
|
||||||
|
c0,0.01,0,0.02,0.01,0.04C296.56,421.64,296.23,421.5,296.14,421.35z M296.45,417.75c0,0,0.2-0.01,0.22,0.1
|
||||||
|
c0.01,0.11,0.01,0.57-0.25,0.67C296.42,418.52,296.27,417.96,296.45,417.75z M298.97,417.72c0.02-0.05,0.09-0.16,0.23-0.28
|
||||||
|
c0.15-0.12,0.31-0.19,0.36-0.21C299.5,417.61,299.11,417.7,298.97,417.72z M300.03,421.44c0.15-0.06,0.54-2.56,0.56-2.76
|
||||||
|
c0.01-0.19-0.08-0.32-0.11-0.5c-0.03-0.18-0.39-0.17-0.39-0.17s-0.52-0.85-0.52-0.84c-0.01,0-0.21,0.07-0.4,0.23
|
||||||
|
c-0.19,0.16-0.25,0.31-0.25,0.32h0l0.67,0.72c-0.07,0.19,0.35,0.25,0.42,0.49c0.07,0.24-0.38,1.42-0.53,1.49
|
||||||
|
c-0.15,0.07-1-0.91-1.18-1.14c-0.18-0.24-0.7-0.42-0.7-0.42c-0.1-0.14-0.11-0.4,0.03-0.61c0.14-0.21,0.4-0.11,0.63-0.14
|
||||||
|
c0.22-0.03,0.08-0.45,0.07-0.57c-0.01-0.13,0.11-0.08,0.18-0.11c0.07-0.03-0.05-0.24-0.14-0.34c-0.08-0.1-0.1-0.27-0.13-0.61
|
||||||
|
c-0.03-0.35-0.64-0.68-1.11-0.67c-0.47,0.01-0.71,0.25-0.86,0.49c-0.15,0.24-0.14,0.27-0.32,0.17c-0.18-0.1-0.24,0.55-0.42,0.77
|
||||||
|
c-0.18,0.22-0.21,1.17-0.21,1.17l0.58,0.88c-0.6,0.4-1.35,1.53-1.44,1.73c-0.08,0.19-0.04,0.24,0.6,0.61
|
||||||
|
c0.52,0.3,1.43,0.59,1.76,0.69c-0.07,0.88-0.61,1.36-0.69,1.68c-0.1,0.39,0.18,0.85,0.39,1.1c0.21,0.25,0.11,0.61,0.11,0.61
|
||||||
|
l0.92,0.11l0.91-0.13l0.95-0.25c-0.14-0.24-0.06-0.68,0-1c0.06-0.32,0.78-0.64,0.84-1.39c0.05-0.75-0.99-1.85-0.99-1.85
|
||||||
|
C299.38,421.42,299.87,421.5,300.03,421.44z"/>
|
||||||
|
<path class="st0" d="M300.21,424.88l-5.92-8.32c0.85-0.63,1.9-1.01,3.04-1.01c2.82,0,5.11,2.29,5.11,5.11
|
||||||
|
C302.43,422.41,301.55,423.96,300.21,424.88z M292.22,420.66c0-1.48,0.63-2.81,1.63-3.74l5.87,8.25c-0.72,0.38-1.53,0.6-2.4,0.6
|
||||||
|
C294.51,425.77,292.22,423.48,292.22,420.66z M297.32,414.99c-3.13,0-5.67,2.54-5.67,5.67c0,3.13,2.54,5.67,5.67,5.67
|
||||||
|
c3.13,0,5.67-2.54,5.67-5.67C302.99,417.54,300.45,414.99,297.32,414.99z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
11
src/assets/PRODUIT DE FRANCE.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
.st1{font-family:'Helvetica';}
|
||||||
|
.st2{font-size:6px;}
|
||||||
|
</style>
|
||||||
|
<text transform="matrix(0.66 0 0 1 289.8221 375.1115)" class="st0 st1 st2">PRODUCE OF FRANCE</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 577 B |
11
src/assets/QUALITÉ.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
.st1{font-family:'Helvetica';}
|
||||||
|
.st2{font-size:14px;}
|
||||||
|
</style>
|
||||||
|
<text transform="matrix(0.66 0 0 1 299.1375 375.1115)" class="st0 st1 st2">BRUT</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 565 B |
11
src/assets/centilitrage.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
.st1{font-family:'GaramondThree';}
|
||||||
|
.st2{font-size:20px;}
|
||||||
|
</style>
|
||||||
|
<text transform="matrix(0.4084 0 0 1 283.9296 426.5225)" class="st0 st1 st2">750 ml</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 573 B |
11
src/assets/sulfites.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
.st1{font-family:'Helvetica';}
|
||||||
|
.st2{font-size:6px;}
|
||||||
|
</style>
|
||||||
|
<text transform="matrix(0.66 0 0 1 286.9607 375.1115)" class="st0 st1 st2">Contient des sulfites</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 581 B |
11
src/assets/ÉLABORATION.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#CDA150;}
|
||||||
|
.st1{font-family:'Helvetica';}
|
||||||
|
.st2{font-size:6px;}
|
||||||
|
</style>
|
||||||
|
<text transform="matrix(0.66 0 0 1 254.2979 375.1115)" class="st0 st1 st2">ÉLABORÉ PAR ERAL CHARLES DELROCHE, 51200 ÉPERNAY, FRANCE - RM-00000-01</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 633 B |
@@ -12,6 +12,8 @@ import {
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Toolbar } from "@/components/toolbar";
|
import { Toolbar } from "@/components/toolbar";
|
||||||
import TransformableText from "@/components/transformable-text";
|
import TransformableText from "@/components/transformable-text";
|
||||||
|
import LayerBorder from "@/components/layer-border";
|
||||||
|
import { CANVAS_PADDING_X, CANVAS_PADDING_Y } from "@/consts/canvas-params";
|
||||||
|
|
||||||
const Canvas = () => {
|
const Canvas = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -33,7 +35,6 @@ const Canvas = () => {
|
|||||||
if (!clickedOnEmpty) {
|
if (!clickedOnEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(target);
|
|
||||||
dispatch(deselectItem());
|
dispatch(deselectItem());
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,42 +55,6 @@ const Canvas = () => {
|
|||||||
setSelected(!isEditing);
|
setSelected(!isEditing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function toggleTransforming() {
|
|
||||||
// setIsTransforming(!isTransforming);
|
|
||||||
// setSelected(!isTransforming);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const handleWheel = (e: Konva.KonvaEventObject<WheelEvent>) => {
|
|
||||||
// e.evt.preventDefault();
|
|
||||||
//
|
|
||||||
// const scaleBy = 1.02;
|
|
||||||
// const targetStage = e.target.getStage()!;
|
|
||||||
// const oldScale = targetStage.scaleX();
|
|
||||||
//
|
|
||||||
// const mousePointTo = {
|
|
||||||
// x:
|
|
||||||
// targetStage.getPointerPosition().x / oldScale -
|
|
||||||
// targetStage.x() / oldScale,
|
|
||||||
// y:
|
|
||||||
// targetStage.getPointerPosition().y / oldScale -
|
|
||||||
// targetStage.y() / oldScale,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// const newScale = e.evt.deltaY < 0 ? oldScale * scaleBy : oldScale / scaleBy;
|
|
||||||
//
|
|
||||||
// dispatch(
|
|
||||||
// setStageScale({
|
|
||||||
// scale: newScale,
|
|
||||||
// x:
|
|
||||||
// (targetStage.getPointerPosition().x / newScale - mousePointTo.x) *
|
|
||||||
// newScale,
|
|
||||||
// y:
|
|
||||||
// (targetStage.getPointerPosition().y / newScale - mousePointTo.y) *
|
|
||||||
// newScale,
|
|
||||||
// }),
|
|
||||||
// );
|
|
||||||
// };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex h-full w-full flex-col items-center">
|
<div className="relative flex h-full w-full flex-col items-center">
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
@@ -112,7 +77,6 @@ const Canvas = () => {
|
|||||||
y={stage.y}
|
y={stage.y}
|
||||||
scaleX={stage.scale}
|
scaleX={stage.scale}
|
||||||
scaleY={stage.scale}
|
scaleY={stage.scale}
|
||||||
// onWheel={handleWheel}
|
|
||||||
>
|
>
|
||||||
<Layer>
|
<Layer>
|
||||||
{!!backgroundRect && (
|
{!!backgroundRect && (
|
||||||
@@ -125,7 +89,14 @@ const Canvas = () => {
|
|||||||
id={backgroundId}
|
id={backgroundId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{items.map((item) => {
|
</Layer>
|
||||||
|
<Layer
|
||||||
|
clipX={CANVAS_PADDING_X}
|
||||||
|
clipY={CANVAS_PADDING_Y}
|
||||||
|
clipWidth={stage.width - 2 * CANVAS_PADDING_X}
|
||||||
|
clipHeight={stage.height - 2 * CANVAS_PADDING_Y}
|
||||||
|
>
|
||||||
|
{items.toReversed().map((item) => {
|
||||||
if (item.type === StageItemType.Image) {
|
if (item.type === StageItemType.Image) {
|
||||||
return (
|
return (
|
||||||
<TransformableImage
|
<TransformableImage
|
||||||
@@ -158,24 +129,9 @@ const Canvas = () => {
|
|||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
</Layer>
|
</Layer>
|
||||||
{/* <Layer>
|
{/*<Legales />*/}
|
||||||
<Rect
|
|
||||||
x={50}
|
<LayerBorder />
|
||||||
y={220}
|
|
||||||
fontSize={48}
|
|
||||||
width={100}
|
|
||||||
height={100}
|
|
||||||
fill="red"
|
|
||||||
/>
|
|
||||||
<Rect
|
|
||||||
x={30}
|
|
||||||
y={200}
|
|
||||||
fontSize={48}
|
|
||||||
width={100}
|
|
||||||
height={100}
|
|
||||||
fill="yellow"
|
|
||||||
/>
|
|
||||||
</Layer>*/}
|
|
||||||
</Stage>
|
</Stage>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { TbFlipHorizontal, TbFlipVertical } from "react-icons/tb";
|
import { TbFlipHorizontal, TbFlipVertical } from "react-icons/tb";
|
||||||
|
import { BsArrowsFullscreen } from "react-icons/Bs";
|
||||||
import { Toggle } from "@/components/ui/toggle";
|
import { Toggle } from "@/components/ui/toggle";
|
||||||
import { useAppDispatch } from "@/hooks";
|
import { useAppDispatch, useAppSelector } from "@/hooks";
|
||||||
import { type StageImageItem, updateImage } from "@/store/app.slice";
|
import { type StageImageItem, updateImage } from "@/store/app.slice";
|
||||||
import ImageOpacityTool from "@/components/image-editing-tools/image-opacity-tool";
|
import ImageOpacityTool from "@/components/image-editing-tools/image-opacity-tool";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { CANVAS_PADDING_X, CANVAS_PADDING_Y } from "@/consts/canvas-params";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
selectedItemId: string;
|
selectedItemId: string;
|
||||||
@@ -13,6 +15,9 @@ type Props = {
|
|||||||
|
|
||||||
export function ImageToolbar({ selectedItemId, currentImage }: Props) {
|
export function ImageToolbar({ selectedItemId, currentImage }: Props) {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const stageParams = useAppSelector((state) => state.app.stage);
|
||||||
|
|
||||||
const flipImageVerticaly = () => {
|
const flipImageVerticaly = () => {
|
||||||
const currentScale = currentImage.scaleY;
|
const currentScale = currentImage.scaleY;
|
||||||
let editOffsetY = currentImage.height;
|
let editOffsetY = currentImage.height;
|
||||||
@@ -40,6 +45,19 @@ export function ImageToolbar({ selectedItemId, currentImage }: Props) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setAsBackground = () => {
|
||||||
|
dispatch(
|
||||||
|
updateImage({
|
||||||
|
id: selectedItemId,
|
||||||
|
x: CANVAS_PADDING_X,
|
||||||
|
y: CANVAS_PADDING_Y,
|
||||||
|
width: stageParams.width - 2 * CANVAS_PADDING_X,
|
||||||
|
height: stageParams.height - 2 * CANVAS_PADDING_Y,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toggle onClick={() => flipImageHorizontaly()}>
|
<Toggle onClick={() => flipImageHorizontaly()}>
|
||||||
@@ -53,6 +71,9 @@ export function ImageToolbar({ selectedItemId, currentImage }: Props) {
|
|||||||
selectedItemId={selectedItemId}
|
selectedItemId={selectedItemId}
|
||||||
currentImage={currentImage}
|
currentImage={currentImage}
|
||||||
/>
|
/>
|
||||||
|
<Toggle onClick={() => setAsBackground()}>
|
||||||
|
<BsArrowsFullscreen />
|
||||||
|
</Toggle>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/components/layer-border.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Layer, Line } from "react-konva";
|
||||||
|
import {
|
||||||
|
CANVAS_PADDING_X,
|
||||||
|
CANVAS_PADDING_Y,
|
||||||
|
DASH_SPACING,
|
||||||
|
DASH_STROKE_COLOR,
|
||||||
|
DASH_STROKE_WIDTH,
|
||||||
|
DASH_WIDTH,
|
||||||
|
} from "@/consts/canvas-params";
|
||||||
|
import { useAppSelector } from "@/hooks";
|
||||||
|
|
||||||
|
export default function LayerBorder() {
|
||||||
|
const stage = useAppSelector((state) => state.app.stage);
|
||||||
|
return (
|
||||||
|
<Layer>
|
||||||
|
<Line
|
||||||
|
points={[
|
||||||
|
CANVAS_PADDING_X,
|
||||||
|
CANVAS_PADDING_Y,
|
||||||
|
stage.width - CANVAS_PADDING_X,
|
||||||
|
CANVAS_PADDING_Y,
|
||||||
|
]}
|
||||||
|
stroke={DASH_STROKE_COLOR}
|
||||||
|
strokeWidth={DASH_STROKE_WIDTH}
|
||||||
|
dash={[DASH_WIDTH, DASH_SPACING]}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
points={[
|
||||||
|
CANVAS_PADDING_X,
|
||||||
|
CANVAS_PADDING_Y,
|
||||||
|
CANVAS_PADDING_X,
|
||||||
|
stage.height - CANVAS_PADDING_Y,
|
||||||
|
]}
|
||||||
|
stroke={DASH_STROKE_COLOR}
|
||||||
|
strokeWidth={DASH_STROKE_WIDTH}
|
||||||
|
dash={[DASH_WIDTH, DASH_SPACING]}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
points={[
|
||||||
|
CANVAS_PADDING_X,
|
||||||
|
stage.height - CANVAS_PADDING_Y,
|
||||||
|
stage.width - CANVAS_PADDING_X,
|
||||||
|
stage.height - CANVAS_PADDING_Y,
|
||||||
|
]}
|
||||||
|
stroke={DASH_STROKE_COLOR}
|
||||||
|
strokeWidth={DASH_STROKE_WIDTH}
|
||||||
|
dash={[DASH_WIDTH, DASH_SPACING]}
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
points={[
|
||||||
|
stage.width - CANVAS_PADDING_X,
|
||||||
|
CANVAS_PADDING_Y,
|
||||||
|
stage.width - CANVAS_PADDING_X,
|
||||||
|
stage.height - CANVAS_PADDING_Y,
|
||||||
|
]}
|
||||||
|
stroke={DASH_STROKE_COLOR}
|
||||||
|
strokeWidth={DASH_STROKE_WIDTH}
|
||||||
|
dash={[DASH_WIDTH, DASH_SPACING]}
|
||||||
|
/>
|
||||||
|
</Layer>
|
||||||
|
);
|
||||||
|
}
|
||||||
42
src/components/layer-item.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useSortable } from "@dnd-kit/sortable";
|
||||||
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
|
import { type StageItem, StageItemType } from "@/store/app.slice";
|
||||||
|
import { useAppDispatch } from "@/hooks";
|
||||||
|
|
||||||
|
export default function LayerItem({ item }: { item: StageItem }) {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { attributes, listeners, setNodeRef, transform, transition } =
|
||||||
|
useSortable({
|
||||||
|
id: item.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
transform: CSS.Transform.toString(transform),
|
||||||
|
transition,
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={style}
|
||||||
|
ref={setNodeRef}
|
||||||
|
{...attributes}
|
||||||
|
{...listeners}
|
||||||
|
className="m-2 flex items-center justify-between rounded-md border p-2 text-black"
|
||||||
|
>
|
||||||
|
{item.type === StageItemType.Text ? (
|
||||||
|
item.params.text < 5 ? (
|
||||||
|
item.params.text
|
||||||
|
) : (
|
||||||
|
item.params.text?.substring(0, 5) + "..."
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<img
|
||||||
|
className="max-h-8 w-8"
|
||||||
|
alt={item.params.imageUrl}
|
||||||
|
src={item.params.imageUrl}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<span className="">{item.type}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { UserNav } from "./user-nav";
|
import { UserNav } from "./user-nav";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import logo from "@/assets/logo.png";
|
import logo from "@/assets/logo.png";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
|
||||||
export const Navbar = () => {
|
export const Navbar = () => {
|
||||||
return (
|
return (
|
||||||
@@ -12,7 +13,7 @@ export const Navbar = () => {
|
|||||||
alt="Logo"
|
alt="Logo"
|
||||||
layout="fill" // required
|
layout="fill" // required
|
||||||
objectFit="cover" // change as you like
|
objectFit="cover" // change as you like
|
||||||
className="rounded-full" // you can use other classes here too
|
className="rounded-full object-cover" // you can use other classes here too
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-auto flex items-center space-x-4">
|
<div className="ml-auto flex items-center space-x-4">
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { RxLayout } from "react-icons/rx";
|
import { RxLayout } from "react-icons/rx";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { useAppDispatch } from "@/hooks";
|
import { useAppDispatch, useAppSelector } from "@/hooks";
|
||||||
import { selectBackground } from "@/store/app.slice";
|
import { selectBackground } from "@/store/app.slice";
|
||||||
|
|
||||||
export const BackgroundSelect = () => {
|
export const BackgroundSelect = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const bgColor = useAppSelector((state) => state.app.background);
|
||||||
|
|
||||||
const handleBackgroundSelect = (color: string) => {
|
const handleBackgroundSelect = (color: string) => {
|
||||||
dispatch(selectBackground(color));
|
dispatch(selectBackground(color));
|
||||||
@@ -40,30 +41,17 @@ export const BackgroundSelect = () => {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="grid grid-cols-2 gap-2">
|
<CardContent className="grid grid-cols-2 gap-2">
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
|
||||||
onClick={() => handleBackgroundSelect("red")}
|
|
||||||
>
|
|
||||||
Red
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label
|
|
||||||
htmlFor="paypal"
|
|
||||||
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
|
||||||
onClick={() => handleBackgroundSelect("blue")}
|
|
||||||
>
|
|
||||||
Blue
|
|
||||||
</Label>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<Label
|
<Label
|
||||||
htmlFor="apple"
|
htmlFor="apple"
|
||||||
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
||||||
onClick={() => handleBackgroundSelect("green")}
|
|
||||||
>
|
>
|
||||||
Green
|
<input
|
||||||
|
className="m-2 "
|
||||||
|
type="color"
|
||||||
|
value={bgColor}
|
||||||
|
onChange={(e) => handleBackgroundSelect(e.target.value)}
|
||||||
|
/>
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -8,19 +8,26 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { RxStack } from "react-icons/rx";
|
import { RxStack } from "react-icons/rx";
|
||||||
import { useAppDispatch, useAppSelector } from "@/hooks";
|
import { useAppDispatch, useAppSelector } from "@/hooks";
|
||||||
import { OrderDirection, updateItemOrder } from "@/store/app.slice";
|
import { selectItem, setStageItems } from "@/store/app.slice";
|
||||||
|
import { closestCenter, DndContext, type DragEndEvent } from "@dnd-kit/core";
|
||||||
|
import {
|
||||||
|
arrayMove,
|
||||||
|
SortableContext,
|
||||||
|
verticalListSortingStrategy,
|
||||||
|
} from "@dnd-kit/sortable";
|
||||||
|
import LayerItem from "@/components/layer-item";
|
||||||
|
|
||||||
export const Layers = () => {
|
export const Layers = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const items = useAppSelector((state) => state.app.items);
|
const items = useAppSelector((state) => state.app.items);
|
||||||
|
|
||||||
const updateImageLayer = (id: string, direction: OrderDirection) => {
|
const handleDragEnd = (e: DragEndEvent) => {
|
||||||
dispatch(
|
const { active, over } = e;
|
||||||
updateItemOrder({
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
id,
|
const newIndex = items.findIndex((item) => item.id === over?.id);
|
||||||
direction,
|
const result = arrayMove(items, oldIndex, newIndex);
|
||||||
}),
|
dispatch(setStageItems(result));
|
||||||
);
|
dispatch(selectItem(active.id));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -33,26 +40,22 @@ export const Layers = () => {
|
|||||||
<PopoverContent side="right">
|
<PopoverContent side="right">
|
||||||
<Card className="p-2">
|
<Card className="p-2">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-center">Layer</CardTitle>
|
<CardTitle className="text-center">Layers</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="grid gap-2">
|
<CardContent className="grid items-center gap-2 p-2 ">
|
||||||
{items.map((item) => (
|
<DndContext
|
||||||
<div key={item.id} className="flex items-center gap-2 ">
|
collisionDetection={closestCenter}
|
||||||
{item.id}
|
onDragEnd={handleDragEnd}
|
||||||
<Button
|
>
|
||||||
className="h-full"
|
<SortableContext
|
||||||
onClick={() => updateImageLayer(item.id, OrderDirection.Up)}
|
items={items}
|
||||||
>
|
strategy={verticalListSortingStrategy}
|
||||||
+
|
>
|
||||||
</Button>
|
{items.map((item) => (
|
||||||
<Button
|
<LayerItem item={item} key={item.id} />
|
||||||
className="h-full"
|
))}
|
||||||
onClick={() => updateImageLayer(item.id, OrderDirection.Down)}
|
</SortableContext>
|
||||||
>
|
</DndContext>
|
||||||
-
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
|
|||||||
0
src/components/layout/sidebar/legacy.tsx
Normal file
@@ -1,33 +1,69 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { PiFrameCornersDuotone } from "react-icons/pi";
|
|
||||||
import { useAppDispatch } from "@/hooks";
|
|
||||||
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { useAppDispatch } from "@/hooks";
|
||||||
|
import { LuLayoutTemplate } from "react-icons/lu";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
|
||||||
export function SelectTemplate() {
|
export const SelectTemplate = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleSizeSelect = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Popover>
|
<Popover open={open} onOpenChange={setOpen}>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button variant="secondary" className="text-xl">
|
<Button
|
||||||
<PiFrameCornersDuotone />
|
onClick={() => setOpen(true)}
|
||||||
|
variant="outline"
|
||||||
|
className="text-xl"
|
||||||
|
>
|
||||||
|
<LuLayoutTemplate />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="right">
|
<PopoverContent side="right" className="mt-4">
|
||||||
{/*<Input type="file" onChange={handleImageUploaded} />*/}
|
<Card className="p-3">
|
||||||
|
<CardHeader className="mb-2 p-2 text-center">
|
||||||
<Card className="p-2">
|
<CardTitle>Template</CardTitle>
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="text-center">Cadre</CardTitle>
|
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
|
<ScrollArea>
|
||||||
|
<div className="flex h-64 w-full flex-col items-center justify-between gap-4">
|
||||||
|
<div className="rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>{" "}
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>{" "}
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>{" "}
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>{" "}
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>{" "}
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>{" "}
|
||||||
|
<div className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary">
|
||||||
|
Image
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
</Card>
|
</Card>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import ImageInput from "@/components/layout/sidebar/image-input";
|
|||||||
import SizeSelect from "@/components/layout/sidebar/size-select";
|
import SizeSelect from "@/components/layout/sidebar/size-select";
|
||||||
import { BackgroundSelect } from "@/components/layout/sidebar/background-select";
|
import { BackgroundSelect } from "@/components/layout/sidebar/background-select";
|
||||||
import { Layers } from "@/components/layout/sidebar/layers";
|
import { Layers } from "@/components/layout/sidebar/layers";
|
||||||
|
import { SelectTemplate } from "@/components/layout/sidebar/select-template";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
@@ -10,7 +12,7 @@ export function Sidebar() {
|
|||||||
<SizeSelect />
|
<SizeSelect />
|
||||||
<TextInput />
|
<TextInput />
|
||||||
<ImageInput />
|
<ImageInput />
|
||||||
{/*<SelectTemplate />*/}
|
<SelectTemplate />
|
||||||
<BackgroundSelect />
|
<BackgroundSelect />
|
||||||
<Layers />
|
<Layers />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -42,13 +42,13 @@ const SizeSelect = () => {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<Button onClick={() => handleStageSizeSelect(350, 400)}>
|
<Button onClick={() => handleStageSizeSelect(269.32, 165.87)}>
|
||||||
Petit Format
|
Petit Format
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => handleStageSizeSelect(500, 500)}>
|
<Button onClick={() => handleStageSizeSelect(323.15, 227)}>
|
||||||
Moyen Format
|
Moyen Format
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => handleStageSizeSelect(800, 600)}>
|
<Button onClick={() => handleStageSizeSelect(410, 289)}>
|
||||||
Grand Format
|
Grand Format
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
20
src/components/legales.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Image, Layer } from "react-konva";
|
||||||
|
import women from "../assets/logo.png";
|
||||||
|
import useImage from "use-image";
|
||||||
|
|
||||||
|
export default function Legales() {
|
||||||
|
const [test] = useImage(women);
|
||||||
|
return (
|
||||||
|
<Layer>
|
||||||
|
<Image
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
|
x={200}
|
||||||
|
y={200}
|
||||||
|
alt={women}
|
||||||
|
image={test}
|
||||||
|
/>
|
||||||
|
</Layer>
|
||||||
|
);
|
||||||
|
}
|
||||||
46
src/components/ui/scroll-area.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const ScrollArea = React.forwardRef<
|
||||||
|
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<ScrollAreaPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn("relative overflow-hidden", className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
||||||
|
{children}
|
||||||
|
</ScrollAreaPrimitive.Viewport>
|
||||||
|
<ScrollBar />
|
||||||
|
<ScrollAreaPrimitive.Corner />
|
||||||
|
</ScrollAreaPrimitive.Root>
|
||||||
|
));
|
||||||
|
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
||||||
|
|
||||||
|
const ScrollBar = React.forwardRef<
|
||||||
|
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||||
|
>(({ className, orientation = "vertical", ...props }, ref) => (
|
||||||
|
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||||
|
ref={ref}
|
||||||
|
orientation={orientation}
|
||||||
|
className={cn(
|
||||||
|
"flex touch-none select-none transition-colors",
|
||||||
|
orientation === "vertical" &&
|
||||||
|
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
||||||
|
orientation === "horizontal" &&
|
||||||
|
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
||||||
|
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||||
|
));
|
||||||
|
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
||||||
|
|
||||||
|
export { ScrollArea, ScrollBar };
|
||||||
27
src/components/ui/switch.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as SwitchPrimitives from "@radix-ui/react-switch"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Switch = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SwitchPrimitives.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SwitchPrimitives.Root
|
||||||
|
className={cn(
|
||||||
|
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
<SwitchPrimitives.Thumb
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SwitchPrimitives.Root>
|
||||||
|
))
|
||||||
|
Switch.displayName = SwitchPrimitives.Root.displayName
|
||||||
|
|
||||||
|
export { Switch }
|
||||||
117
src/components/ui/table.tsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Table = React.forwardRef<
|
||||||
|
HTMLTableElement,
|
||||||
|
React.HTMLAttributes<HTMLTableElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div className="relative w-full overflow-auto">
|
||||||
|
<table
|
||||||
|
ref={ref}
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
Table.displayName = "Table"
|
||||||
|
|
||||||
|
const TableHeader = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
||||||
|
))
|
||||||
|
TableHeader.displayName = "TableHeader"
|
||||||
|
|
||||||
|
const TableBody = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tbody
|
||||||
|
ref={ref}
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableBody.displayName = "TableBody"
|
||||||
|
|
||||||
|
const TableFooter = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tfoot
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableFooter.displayName = "TableFooter"
|
||||||
|
|
||||||
|
const TableRow = React.forwardRef<
|
||||||
|
HTMLTableRowElement,
|
||||||
|
React.HTMLAttributes<HTMLTableRowElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tr
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableRow.displayName = "TableRow"
|
||||||
|
|
||||||
|
const TableHead = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<th
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableHead.displayName = "TableHead"
|
||||||
|
|
||||||
|
const TableCell = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<td
|
||||||
|
ref={ref}
|
||||||
|
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableCell.displayName = "TableCell"
|
||||||
|
|
||||||
|
const TableCaption = React.forwardRef<
|
||||||
|
HTMLTableCaptionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableCaptionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<caption
|
||||||
|
ref={ref}
|
||||||
|
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableCaption.displayName = "TableCaption"
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
}
|
||||||
6
src/consts/canvas-params.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const CANVAS_PADDING_X = 20;
|
||||||
|
export const CANVAS_PADDING_Y = 20;
|
||||||
|
export const DASH_WIDTH = 5;
|
||||||
|
export const DASH_SPACING = 3;
|
||||||
|
export const DASH_STROKE_WIDTH = 1;
|
||||||
|
export const DASH_STROKE_COLOR = "#c6a25e";
|
||||||
@@ -13,7 +13,6 @@ export enum StageItemType {
|
|||||||
|
|
||||||
type StageItemCommon = {
|
type StageItemCommon = {
|
||||||
id: string;
|
id: string;
|
||||||
order: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StageTextItem = {
|
export type StageTextItem = {
|
||||||
@@ -28,7 +27,7 @@ export type StageImageItem = {
|
|||||||
|
|
||||||
type StageItemSpecific = StageTextItem | StageImageItem;
|
type StageItemSpecific = StageTextItem | StageImageItem;
|
||||||
|
|
||||||
type StageItem = StageItemCommon & StageItemSpecific;
|
export type StageItem = StageItemCommon & StageItemSpecific;
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
stage: { width: 500, height: 500, scale: 1, x: 0, y: 0 },
|
stage: { width: 500, height: 500, scale: 1, x: 0, y: 0 },
|
||||||
@@ -57,15 +56,13 @@ const defaultImageConfig = {
|
|||||||
scaleY: 1,
|
scaleY: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum OrderDirection {
|
|
||||||
Up = "up",
|
|
||||||
Down = "down",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const appSlice = createSlice({
|
export const appSlice = createSlice({
|
||||||
name: "app",
|
name: "app",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
|
setStageItems: (state, action: PayloadAction<StageItem[]>) => {
|
||||||
|
state.items = action.payload;
|
||||||
|
},
|
||||||
setStageScale: (
|
setStageScale: (
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{ x: number; y: number; scale: number }>,
|
action: PayloadAction<{ x: number; y: number; scale: number }>,
|
||||||
@@ -80,7 +77,6 @@ export const appSlice = createSlice({
|
|||||||
state.items.push({
|
state.items.push({
|
||||||
type: StageItemType.Text,
|
type: StageItemType.Text,
|
||||||
id: textId,
|
id: textId,
|
||||||
order: state.items.length + 1,
|
|
||||||
params: {
|
params: {
|
||||||
text: action.payload.initialValue,
|
text: action.payload.initialValue,
|
||||||
|
|
||||||
@@ -102,7 +98,6 @@ export const appSlice = createSlice({
|
|||||||
state.items.push({
|
state.items.push({
|
||||||
type: StageItemType.Image,
|
type: StageItemType.Image,
|
||||||
id: imageId,
|
id: imageId,
|
||||||
order: state.items.length + 1,
|
|
||||||
params: {
|
params: {
|
||||||
imageUrl: action.payload.imageUrl,
|
imageUrl: action.payload.imageUrl,
|
||||||
width: action.payload.width,
|
width: action.payload.width,
|
||||||
@@ -112,83 +107,6 @@ export const appSlice = createSlice({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateImageOrder: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<{ id: string; direction: OrderDirection }>,
|
|
||||||
) => {
|
|
||||||
const imageToUpdateIndex = state.items.findIndex(
|
|
||||||
(img) => img.id === action.payload.id,
|
|
||||||
);
|
|
||||||
const imageToUpdate = state.items[imageToUpdateIndex];
|
|
||||||
|
|
||||||
if (!imageToUpdate) return;
|
|
||||||
const isLast = imageToUpdate.order === state.items.length;
|
|
||||||
const isFirst = imageToUpdate.order === 1;
|
|
||||||
|
|
||||||
let newOrder = imageToUpdate.order;
|
|
||||||
if (action.payload.direction === OrderDirection.Up && !isLast) {
|
|
||||||
newOrder = imageToUpdate.order + 1;
|
|
||||||
}
|
|
||||||
if (action.payload.direction === OrderDirection.Down && !isFirst) {
|
|
||||||
newOrder = imageToUpdate.order - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.items[imageToUpdateIndex] = {
|
|
||||||
...imageToUpdate,
|
|
||||||
order: newOrder,
|
|
||||||
};
|
|
||||||
|
|
||||||
state.items.sort((a, b) => {
|
|
||||||
if (a === b) return 0;
|
|
||||||
if (a < b) return 1;
|
|
||||||
return -1;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
updateItemOrder: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<{ id: string; direction: OrderDirection }>,
|
|
||||||
) => {
|
|
||||||
const itemToUpdateIndex = state.items.findIndex(
|
|
||||||
(item) => item.id === action.payload.id,
|
|
||||||
);
|
|
||||||
const itemToUpdate = state.items[itemToUpdateIndex];
|
|
||||||
|
|
||||||
if (!itemToUpdate) return;
|
|
||||||
const isLast = itemToUpdate.order === state.items.length;
|
|
||||||
const isFirst = itemToUpdate.order === 1;
|
|
||||||
|
|
||||||
let newOrder = itemToUpdate.order;
|
|
||||||
if (action.payload.direction === OrderDirection.Up && !isLast) {
|
|
||||||
newOrder = itemToUpdate.order + 1;
|
|
||||||
}
|
|
||||||
if (action.payload.direction === OrderDirection.Down && !isFirst) {
|
|
||||||
newOrder = itemToUpdate.order - 1;
|
|
||||||
}
|
|
||||||
const prevItemIndex = state.items.findIndex(
|
|
||||||
(item) => item.order === newOrder,
|
|
||||||
);
|
|
||||||
const prevItem = state.items[prevItemIndex];
|
|
||||||
|
|
||||||
if (!prevItem) return;
|
|
||||||
|
|
||||||
state.items[prevItemIndex] = {
|
|
||||||
...prevItem,
|
|
||||||
order: itemToUpdate.order,
|
|
||||||
};
|
|
||||||
|
|
||||||
state.items[itemToUpdateIndex] = {
|
|
||||||
...itemToUpdate,
|
|
||||||
order: newOrder,
|
|
||||||
};
|
|
||||||
|
|
||||||
state.items.sort((a, b) => {
|
|
||||||
if (a === b) return 0;
|
|
||||||
if (a < b) return 1;
|
|
||||||
return -1;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
selectBackground: (state, action: PayloadAction<string>) => {
|
selectBackground: (state, action: PayloadAction<string>) => {
|
||||||
state.background = {
|
state.background = {
|
||||||
fill: action.payload,
|
fill: action.payload,
|
||||||
@@ -258,15 +176,14 @@ export const appSlice = createSlice({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
setStageScale,
|
|
||||||
addImage,
|
addImage,
|
||||||
addText,
|
addText,
|
||||||
selectItem,
|
|
||||||
deselectItem,
|
deselectItem,
|
||||||
updateText,
|
updateText,
|
||||||
updateImage,
|
updateImage,
|
||||||
deleteStageItem,
|
deleteStageItem,
|
||||||
updateStage,
|
updateStage,
|
||||||
selectBackground,
|
selectBackground,
|
||||||
updateItemOrder,
|
setStageItems,
|
||||||
|
selectItem,
|
||||||
} = appSlice.actions;
|
} = appSlice.actions;
|
||||||
|
|||||||
10
todo.md
@@ -1,4 +1,12 @@
|
|||||||
- text transform box doesn't update it's size on font size change
|
- text transform box doesn't update it's size on font size change
|
||||||
|
|
||||||
- layout order doesn't work correctly with > 2 objects
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Authorization provider
|
||||||
|
- Template properties ( assets )
|
||||||
|
- Canvas sizes
|
||||||
|
- what to add or change?
|
||||||
|
-
|
||||||