feat: add Image Management page and upload dialog
Some checks failed
Frontend CI / build (push) Failing after 1m0s
Some checks failed
Frontend CI / build (push) Failing after 1m0s
This commit is contained in:
parent
e8c5e678d5
commit
731b8e5d8b
@ -20,7 +20,8 @@
|
|||||||
"@eslint/compat": "^1.2.5",
|
"@eslint/compat": "^1.2.5",
|
||||||
"@eslint/js": "^9.18.0",
|
"@eslint/js": "^9.18.0",
|
||||||
"@fortawesome/fontawesome-free": "^7.0.0",
|
"@fortawesome/fontawesome-free": "^7.0.0",
|
||||||
"@lucide/svelte": "^0.545.0",
|
"@internationalized/date": "^3.10.0",
|
||||||
|
"@lucide/svelte": "^0.544.0",
|
||||||
"@sveltejs/adapter-auto": "^6.0.0",
|
"@sveltejs/adapter-auto": "^6.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.2.13",
|
"@sveltejs/adapter-node": "^5.2.13",
|
||||||
"@sveltejs/kit": "^2.22.0",
|
"@sveltejs/kit": "^2.22.0",
|
||||||
@ -29,6 +30,7 @@
|
|||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"@types/markdown-it": "^14.1.2",
|
"@types/markdown-it": "^14.1.2",
|
||||||
"@types/sanitize-html": "^2.16.0",
|
"@types/sanitize-html": "^2.16.0",
|
||||||
|
"bits-ui": "^2.11.5",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
|
118
frontend/pnpm-lock.yaml
generated
118
frontend/pnpm-lock.yaml
generated
@ -21,9 +21,12 @@ importers:
|
|||||||
'@fortawesome/fontawesome-free':
|
'@fortawesome/fontawesome-free':
|
||||||
specifier: ^7.0.0
|
specifier: ^7.0.0
|
||||||
version: 7.0.0
|
version: 7.0.0
|
||||||
|
'@internationalized/date':
|
||||||
|
specifier: ^3.10.0
|
||||||
|
version: 3.10.0
|
||||||
'@lucide/svelte':
|
'@lucide/svelte':
|
||||||
specifier: ^0.545.0
|
specifier: ^0.544.0
|
||||||
version: 0.545.0(svelte@5.36.13)
|
version: 0.544.0(svelte@5.36.13)
|
||||||
'@sveltejs/adapter-auto':
|
'@sveltejs/adapter-auto':
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.0.1(@sveltejs/kit@2.25.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.13)(vite@7.0.5(@types/node@24.2.0)(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.13)(vite@7.0.5(@types/node@24.2.0)(jiti@2.4.2)(lightningcss@1.30.1)))
|
version: 6.0.1(@sveltejs/kit@2.25.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.13)(vite@7.0.5(@types/node@24.2.0)(jiti@2.4.2)(lightningcss@1.30.1)))(svelte@5.36.13)(vite@7.0.5(@types/node@24.2.0)(jiti@2.4.2)(lightningcss@1.30.1)))
|
||||||
@ -48,6 +51,9 @@ importers:
|
|||||||
'@types/sanitize-html':
|
'@types/sanitize-html':
|
||||||
specifier: ^2.16.0
|
specifier: ^2.16.0
|
||||||
version: 2.16.0
|
version: 2.16.0
|
||||||
|
bits-ui:
|
||||||
|
specifier: ^2.11.5
|
||||||
|
version: 2.11.5(@internationalized/date@3.10.0)(svelte@5.36.13)
|
||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
@ -390,6 +396,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==}
|
resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
|
'@floating-ui/core@1.7.3':
|
||||||
|
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.7.4':
|
||||||
|
resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==}
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.10':
|
||||||
|
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
|
||||||
|
|
||||||
'@fortawesome/fontawesome-free@7.0.0':
|
'@fortawesome/fontawesome-free@7.0.0':
|
||||||
resolution: {integrity: sha512-X48nISrSOa89zu2VMljC4XaRf8NmgTwQBVHfS2Nu5G00ZwM31oOVrAtGxZF3b6wDYf9lJsf/Eq4cCSFKIkOWPQ==}
|
resolution: {integrity: sha512-X48nISrSOa89zu2VMljC4XaRf8NmgTwQBVHfS2Nu5G00ZwM31oOVrAtGxZF3b6wDYf9lJsf/Eq4cCSFKIkOWPQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -414,6 +429,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||||
engines: {node: '>=18.18'}
|
engines: {node: '>=18.18'}
|
||||||
|
|
||||||
|
'@internationalized/date@3.10.0':
|
||||||
|
resolution: {integrity: sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw==}
|
||||||
|
|
||||||
'@isaacs/fs-minipass@4.0.1':
|
'@isaacs/fs-minipass@4.0.1':
|
||||||
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
|
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@ -431,8 +449,8 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.29':
|
'@jridgewell/trace-mapping@0.3.29':
|
||||||
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
|
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
|
||||||
|
|
||||||
'@lucide/svelte@0.545.0':
|
'@lucide/svelte@0.544.0':
|
||||||
resolution: {integrity: sha512-RlAtWefx9MdpXaOMbx3Qv3/NqpeZKOIPxN2D0RBN2+op0opKly8VgYEEWZTT6Ow/zf7UwyTg6/0ExJlsVLK+8g==}
|
resolution: {integrity: sha512-9f9O6uxng2pLB01sxNySHduJN3HTl5p0HDu4H26VR51vhZfiMzyOMe9Mhof3XAk4l813eTtl+/DYRvGyoRR+yw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
svelte: ^5
|
svelte: ^5
|
||||||
|
|
||||||
@ -964,6 +982,9 @@ packages:
|
|||||||
svelte: ^5.0.0
|
svelte: ^5.0.0
|
||||||
vite: ^6.3.0 || ^7.0.0
|
vite: ^6.3.0 || ^7.0.0
|
||||||
|
|
||||||
|
'@swc/helpers@0.5.17':
|
||||||
|
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
|
||||||
|
|
||||||
'@tailwindcss/node@4.1.11':
|
'@tailwindcss/node@4.1.11':
|
||||||
resolution: {integrity: sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==}
|
resolution: {integrity: sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==}
|
||||||
|
|
||||||
@ -1215,6 +1236,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
bits-ui@2.11.5:
|
||||||
|
resolution: {integrity: sha512-d7b6HrrCUeK261c777agFz0G5lx13RMA0DT022e4SRuIjI3bZ8ci53YxIZ2/jpXTmeAeqeShyC+Mgibh9OeW9A==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
peerDependencies:
|
||||||
|
'@internationalized/date': ^3.8.1
|
||||||
|
svelte: ^5.33.0
|
||||||
|
|
||||||
brace-expansion@1.1.12:
|
brace-expansion@1.1.12:
|
||||||
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
|
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
|
||||||
|
|
||||||
@ -1552,6 +1580,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
|
|
||||||
|
inline-style-parser@0.2.4:
|
||||||
|
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
|
||||||
|
|
||||||
is-binary-path@2.1.0:
|
is-binary-path@2.1.0:
|
||||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -2059,6 +2090,16 @@ packages:
|
|||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||||
|
|
||||||
|
runed@0.29.2:
|
||||||
|
resolution: {integrity: sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^5.7.0
|
||||||
|
|
||||||
|
runed@0.31.1:
|
||||||
|
resolution: {integrity: sha512-v3czcTnO+EJjiPvD4dwIqfTdHLZ8oH0zJheKqAHh9QMViY7Qb29UlAMRpX7ZtHh7AFqV60KmfxaJ9QMy+L1igQ==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^5.7.0
|
||||||
|
|
||||||
sade@1.8.1:
|
sade@1.8.1:
|
||||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -2109,6 +2150,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
style-to-object@1.0.11:
|
||||||
|
resolution: {integrity: sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==}
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -2134,10 +2178,19 @@ packages:
|
|||||||
svelte:
|
svelte:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
svelte-toolbelt@0.10.5:
|
||||||
|
resolution: {integrity: sha512-8e+eWTgxw1aiLxhDE8Rb1X6AoLitqpJz+WhAul2W7W58C8KoLoJQf1TgQdFPBiCPJ0Jg5y0Zi1uyua9em4VS0w==}
|
||||||
|
engines: {node: '>=18', pnpm: '>=8.7.0'}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^5.30.2
|
||||||
|
|
||||||
svelte@5.36.13:
|
svelte@5.36.13:
|
||||||
resolution: {integrity: sha512-LnSywHHQM/nJekC65d84T1Yo85IeCYN4AryWYPhTokSvcEAFdYFCfbMhX1mc0zHizT736QQj0nalUk+SXaWrEQ==}
|
resolution: {integrity: sha512-LnSywHHQM/nJekC65d84T1Yo85IeCYN4AryWYPhTokSvcEAFdYFCfbMhX1mc0zHizT736QQj0nalUk+SXaWrEQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
tabbable@6.2.0:
|
||||||
|
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||||
|
|
||||||
tailwind-merge@3.3.1:
|
tailwind-merge@3.3.1:
|
||||||
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
|
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
|
||||||
|
|
||||||
@ -2564,6 +2617,17 @@ snapshots:
|
|||||||
'@eslint/core': 0.15.1
|
'@eslint/core': 0.15.1
|
||||||
levn: 0.4.1
|
levn: 0.4.1
|
||||||
|
|
||||||
|
'@floating-ui/core@1.7.3':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/utils': 0.2.10
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.7.4':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/core': 1.7.3
|
||||||
|
'@floating-ui/utils': 0.2.10
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.10': {}
|
||||||
|
|
||||||
'@fortawesome/fontawesome-free@7.0.0': {}
|
'@fortawesome/fontawesome-free@7.0.0': {}
|
||||||
|
|
||||||
'@humanfs/core@0.19.1': {}
|
'@humanfs/core@0.19.1': {}
|
||||||
@ -2579,6 +2643,10 @@ snapshots:
|
|||||||
|
|
||||||
'@humanwhocodes/retry@0.4.3': {}
|
'@humanwhocodes/retry@0.4.3': {}
|
||||||
|
|
||||||
|
'@internationalized/date@3.10.0':
|
||||||
|
dependencies:
|
||||||
|
'@swc/helpers': 0.5.17
|
||||||
|
|
||||||
'@isaacs/fs-minipass@4.0.1':
|
'@isaacs/fs-minipass@4.0.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
minipass: 7.1.2
|
minipass: 7.1.2
|
||||||
@ -2597,7 +2665,7 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.4
|
'@jridgewell/sourcemap-codec': 1.5.4
|
||||||
|
|
||||||
'@lucide/svelte@0.545.0(svelte@5.36.13)':
|
'@lucide/svelte@0.544.0(svelte@5.36.13)':
|
||||||
dependencies:
|
dependencies:
|
||||||
svelte: 5.36.13
|
svelte: 5.36.13
|
||||||
|
|
||||||
@ -3216,6 +3284,10 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@swc/helpers@0.5.17':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@tailwindcss/node@4.1.11':
|
'@tailwindcss/node@4.1.11':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ampproject/remapping': 2.3.0
|
'@ampproject/remapping': 2.3.0
|
||||||
@ -3483,6 +3555,17 @@ snapshots:
|
|||||||
|
|
||||||
binary-extensions@2.3.0: {}
|
binary-extensions@2.3.0: {}
|
||||||
|
|
||||||
|
bits-ui@2.11.5(@internationalized/date@3.10.0)(svelte@5.36.13):
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/core': 1.7.3
|
||||||
|
'@floating-ui/dom': 1.7.4
|
||||||
|
'@internationalized/date': 3.10.0
|
||||||
|
esm-env: 1.2.2
|
||||||
|
runed: 0.31.1(svelte@5.36.13)
|
||||||
|
svelte: 5.36.13
|
||||||
|
svelte-toolbelt: 0.10.5(svelte@5.36.13)
|
||||||
|
tabbable: 6.2.0
|
||||||
|
|
||||||
brace-expansion@1.1.12:
|
brace-expansion@1.1.12:
|
||||||
dependencies:
|
dependencies:
|
||||||
balanced-match: 1.0.2
|
balanced-match: 1.0.2
|
||||||
@ -3849,6 +3932,8 @@ snapshots:
|
|||||||
|
|
||||||
imurmurhash@0.1.4: {}
|
imurmurhash@0.1.4: {}
|
||||||
|
|
||||||
|
inline-style-parser@0.2.4: {}
|
||||||
|
|
||||||
is-binary-path@2.1.0:
|
is-binary-path@2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions: 2.3.0
|
binary-extensions: 2.3.0
|
||||||
@ -4233,6 +4318,16 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
|
|
||||||
|
runed@0.29.2(svelte@5.36.13):
|
||||||
|
dependencies:
|
||||||
|
esm-env: 1.2.2
|
||||||
|
svelte: 5.36.13
|
||||||
|
|
||||||
|
runed@0.31.1(svelte@5.36.13):
|
||||||
|
dependencies:
|
||||||
|
esm-env: 1.2.2
|
||||||
|
svelte: 5.36.13
|
||||||
|
|
||||||
sade@1.8.1:
|
sade@1.8.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
mri: 1.2.0
|
mri: 1.2.0
|
||||||
@ -4278,6 +4373,10 @@ snapshots:
|
|||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
|
style-to-object@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
inline-style-parser: 0.2.4
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag: 4.0.0
|
has-flag: 4.0.0
|
||||||
@ -4307,6 +4406,13 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
svelte: 5.36.13
|
svelte: 5.36.13
|
||||||
|
|
||||||
|
svelte-toolbelt@0.10.5(svelte@5.36.13):
|
||||||
|
dependencies:
|
||||||
|
clsx: 2.1.1
|
||||||
|
runed: 0.29.2(svelte@5.36.13)
|
||||||
|
style-to-object: 1.0.11
|
||||||
|
svelte: 5.36.13
|
||||||
|
|
||||||
svelte@5.36.13:
|
svelte@5.36.13:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ampproject/remapping': 2.3.0
|
'@ampproject/remapping': 2.3.0
|
||||||
@ -4324,6 +4430,8 @@ snapshots:
|
|||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
zimmerframe: 1.1.2
|
zimmerframe: 1.1.2
|
||||||
|
|
||||||
|
tabbable@6.2.0: {}
|
||||||
|
|
||||||
tailwind-merge@3.3.1: {}
|
tailwind-merge@3.3.1: {}
|
||||||
|
|
||||||
tailwind-variants@3.1.1(tailwind-merge@3.3.1)(tailwindcss@4.1.11):
|
tailwind-variants@3.1.1(tailwind-merge@3.3.1)(tailwindcss@4.1.11):
|
||||||
|
@ -153,6 +153,10 @@ button {
|
|||||||
@apply cursor-pointer;
|
@apply cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.content-container {
|
||||||
@apply mx-auto max-w-screen-xl px-4 md:px-6;
|
@apply mx-auto max-w-screen-xl px-4 md:px-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-container {
|
||||||
|
@apply mx-auto w-full max-w-screen-lg px-7;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: DialogPrimitive.CloseProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Close bind:ref data-slot="dialog-close" {...restProps} />
|
@ -0,0 +1,43 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
import XIcon from "@lucide/svelte/icons/x";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
import * as Dialog from "./index.js";
|
||||||
|
import { cn, type WithoutChildrenOrChild } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
portalProps,
|
||||||
|
children,
|
||||||
|
showCloseButton = true,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
||||||
|
portalProps?: DialogPrimitive.PortalProps;
|
||||||
|
children: Snippet;
|
||||||
|
showCloseButton?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Dialog.Portal {...portalProps}>
|
||||||
|
<Dialog.Overlay />
|
||||||
|
<DialogPrimitive.Content
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-content"
|
||||||
|
class={cn(
|
||||||
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
{#if showCloseButton}
|
||||||
|
<DialogPrimitive.Close
|
||||||
|
class="ring-offset-background focus:ring-ring rounded-xs focus:outline-hidden absolute end-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
||||||
|
>
|
||||||
|
<XIcon />
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
</DialogPrimitive.Close>
|
||||||
|
{/if}
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</Dialog.Portal>
|
@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DialogPrimitive.DescriptionProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Description
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-description"
|
||||||
|
class={cn("text-muted-foreground text-sm", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from "$lib/common/framework/components/utils.js";
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="dialog-footer"
|
||||||
|
class={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn, type WithElementRef } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="dialog-header"
|
||||||
|
class={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DialogPrimitive.OverlayProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Overlay
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-overlay"
|
||||||
|
class={cn(
|
||||||
|
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DialogPrimitive.TitleProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Title
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-title"
|
||||||
|
class={cn("text-lg font-semibold leading-none", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: DialogPrimitive.TriggerProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Trigger bind:ref data-slot="dialog-trigger" {...restProps} />
|
@ -0,0 +1,37 @@
|
|||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
import Title from "./dialog-title.svelte";
|
||||||
|
import Footer from "./dialog-footer.svelte";
|
||||||
|
import Header from "./dialog-header.svelte";
|
||||||
|
import Overlay from "./dialog-overlay.svelte";
|
||||||
|
import Content from "./dialog-content.svelte";
|
||||||
|
import Description from "./dialog-description.svelte";
|
||||||
|
import Trigger from "./dialog-trigger.svelte";
|
||||||
|
import Close from "./dialog-close.svelte";
|
||||||
|
|
||||||
|
const Root = DialogPrimitive.Root;
|
||||||
|
const Portal = DialogPrimitive.Portal;
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
Title,
|
||||||
|
Portal,
|
||||||
|
Footer,
|
||||||
|
Header,
|
||||||
|
Trigger,
|
||||||
|
Overlay,
|
||||||
|
Content,
|
||||||
|
Description,
|
||||||
|
Close,
|
||||||
|
//
|
||||||
|
Root as Dialog,
|
||||||
|
Title as DialogTitle,
|
||||||
|
Portal as DialogPortal,
|
||||||
|
Footer as DialogFooter,
|
||||||
|
Header as DialogHeader,
|
||||||
|
Trigger as DialogTrigger,
|
||||||
|
Overlay as DialogOverlay,
|
||||||
|
Content as DialogContent,
|
||||||
|
Description as DialogDescription,
|
||||||
|
Close as DialogClose,
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import Root from "./input.svelte";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
//
|
||||||
|
Root as Input,
|
||||||
|
};
|
@ -0,0 +1,52 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
|
||||||
|
import { cn, type WithElementRef } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
|
||||||
|
|
||||||
|
type Props = WithElementRef<
|
||||||
|
Omit<HTMLInputAttributes, "type"> &
|
||||||
|
({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })
|
||||||
|
>;
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable(),
|
||||||
|
type,
|
||||||
|
files = $bindable(),
|
||||||
|
class: className,
|
||||||
|
"data-slot": dataSlot = "input",
|
||||||
|
...restProps
|
||||||
|
}: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if type === "file"}
|
||||||
|
<input
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot={dataSlot}
|
||||||
|
class={cn(
|
||||||
|
"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
|
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||||
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
type="file"
|
||||||
|
bind:files
|
||||||
|
bind:value
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot={dataSlot}
|
||||||
|
class={cn(
|
||||||
|
"border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
|
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||||
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{type}
|
||||||
|
bind:value
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
{/if}
|
@ -0,0 +1,7 @@
|
|||||||
|
import Root from "./label.svelte";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
//
|
||||||
|
Root as Label,
|
||||||
|
};
|
@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Label as LabelPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/common/framework/components/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: LabelPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<LabelPrimitive.Root
|
||||||
|
bind:ref
|
||||||
|
data-slot="label"
|
||||||
|
class={cn(
|
||||||
|
"flex select-none items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { Button } from '$lib/common/framework/components/ui/button/index';
|
import { Button } from '$lib/common/framework/components/ui/button';
|
||||||
import type { DashboardLink } from '$lib/dashboard/framework/ui/dashboardLink';
|
import type { DashboardLink } from '$lib/dashboard/framework/ui/dashboardLink';
|
||||||
|
|
||||||
const { link }: { link: DashboardLink } = $props();
|
const { link }: { link: DashboardLink } = $props();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
const { links }: { links: DashboardLink[] } = $props();
|
const { links }: { links: DashboardLink[] } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-3xs border-e border-true-gray-300 p-8">
|
<div class="border-true-gray-300 w-3xs border-e p-8">
|
||||||
<div class="mb-3 font-bold">Dashboard</div>
|
<div class="mb-3 font-bold">Dashboard</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
{#each links as link (link.href)}
|
{#each links as link (link.href)}
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
import MottoAnimatedMark from './MottoAnimatedMark.svelte';
|
import MottoAnimatedMark from './MottoAnimatedMark.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container flex h-screen flex-col items-center justify-center gap-y-2.5 md:gap-y-8">
|
<div
|
||||||
|
class="content-container flex h-screen flex-col items-center justify-center gap-y-2.5 md:gap-y-8"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex w-[19rem] flex-col gap-y-3 text-3xl font-bold text-gray-800 md:w-[38rem] md:gap-y-4 md:text-6xl"
|
class="flex w-[19rem] flex-col gap-y-3 text-3xl font-bold text-gray-800 md:w-[38rem] md:gap-y-4 md:text-6xl"
|
||||||
>
|
>
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
<meta name="description" content={lines.join(',')} />
|
<meta name="description" content={lines.join(',')} />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<div
|
<div
|
||||||
class="container flex flex-col items-center justify-center gap-y-2.5 py-32 md:gap-y-8 md:px-24 md:py-32"
|
class="content-container flex flex-col items-center justify-center gap-y-2.5 py-32 md:gap-y-8 md:px-24 md:py-32"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
bind:this={element}
|
bind:this={element}
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
import TitleScreenAnimatedTags from '$lib/home/framework/ui/TitleScreenAnimatedTags.svelte';
|
import TitleScreenAnimatedTags from '$lib/home/framework/ui/TitleScreenAnimatedTags.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container flex min-h-content-height flex-col justify-center gap-y-2.5 md:gap-y-8">
|
<div
|
||||||
|
class="content-container flex min-h-content-height flex-col justify-center gap-y-2.5 md:gap-y-8"
|
||||||
|
>
|
||||||
<h2 class="text-3xl font-bold text-gray-800 md:text-6xl">Hello 大家好!</h2>
|
<h2 class="text-3xl font-bold text-gray-800 md:text-6xl">Hello 大家好!</h2>
|
||||||
<h1 class="flex flex-row items-center gap-x-2 text-4xl font-extrabold text-gray-800 md:text-7xl">
|
<h1 class="flex flex-row items-center gap-x-2 text-4xl font-extrabold text-gray-800 md:text-7xl">
|
||||||
<span>我是</span>
|
<span>我是</span>
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
import UploadImageDialoag from './UploadImageDialoag.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="dashboard-container mb-10">
|
||||||
|
<div class="flex flex-row items-center justify-between">
|
||||||
|
<h1 class="py-16 text-5xl font-bold text-gray-800">Image</h1>
|
||||||
|
<UploadImageDialoag />
|
||||||
|
</div>
|
||||||
|
<p>Gallery is currently unavailable.</p>
|
||||||
|
</div>
|
@ -0,0 +1,60 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { buttonVariants } from '$lib/common/framework/components/ui/button';
|
||||||
|
import Button from '$lib/common/framework/components/ui/button/button.svelte';
|
||||||
|
import { Dialog } from '$lib/common/framework/components/ui/dialog';
|
||||||
|
import DialogClose from '$lib/common/framework/components/ui/dialog/dialog-close.svelte';
|
||||||
|
import DialogContent from '$lib/common/framework/components/ui/dialog/dialog-content.svelte';
|
||||||
|
import DialogFooter from '$lib/common/framework/components/ui/dialog/dialog-footer.svelte';
|
||||||
|
import DialogHeader from '$lib/common/framework/components/ui/dialog/dialog-header.svelte';
|
||||||
|
import DialogTitle from '$lib/common/framework/components/ui/dialog/dialog-title.svelte';
|
||||||
|
import DialogTrigger from '$lib/common/framework/components/ui/dialog/dialog-trigger.svelte';
|
||||||
|
import Input from '$lib/common/framework/components/ui/input/input.svelte';
|
||||||
|
import Label from '$lib/common/framework/components/ui/label/label.svelte';
|
||||||
|
|
||||||
|
let files: FileList | undefined = $state(undefined);
|
||||||
|
let fileInputErrorMessage: string | null = $state(null);
|
||||||
|
const isFileInputError = $derived(fileInputErrorMessage !== null);
|
||||||
|
|
||||||
|
function onSubmit(event: SubmitEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
fileInputErrorMessage = null;
|
||||||
|
|
||||||
|
const file = files?.[0];
|
||||||
|
if (!file || !file.type.startsWith('image/')) {
|
||||||
|
fileInputErrorMessage = 'Please select an valid image file.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Submitting file:', file);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger class={buttonVariants({ variant: 'default' })}>Upload</DialogTrigger>
|
||||||
|
<DialogContent showCloseButton={false}>
|
||||||
|
<DialogHeader class="mb-4">
|
||||||
|
<DialogTitle>Upload Image</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<form onsubmit={onSubmit}>
|
||||||
|
<Label for="file-input" class="pb-2">Image File</Label>
|
||||||
|
<Input
|
||||||
|
id="file-input"
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
aria-invalid={isFileInputError}
|
||||||
|
bind:files
|
||||||
|
/>
|
||||||
|
{#if isFileInputError}
|
||||||
|
<p class="text-sm text-red-500">{fileInputErrorMessage}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<DialogFooter class="mt-6">
|
||||||
|
<DialogClose>
|
||||||
|
<Button variant="outline">Cancel</Button>
|
||||||
|
</DialogClose>
|
||||||
|
<Button type="submit">Submit</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PostInfoViewModel } from '$lib/post/adapter/presenter/postInfoViewModel';
|
import type { PostInfoViewModel } from '$lib/post/adapter/presenter/postInfoViewModel';
|
||||||
import Label from '$lib/post/framework/ui/Label.svelte';
|
import PostLabel from '$lib/post/framework/ui/PostLabel.svelte';
|
||||||
|
|
||||||
const { postInfo }: { postInfo: PostInfoViewModel } = $props();
|
const { postInfo }: { postInfo: PostInfoViewModel } = $props();
|
||||||
</script>
|
</script>
|
||||||
@ -8,7 +8,7 @@
|
|||||||
<div class="flex flex-col pt-9 md:pt-20">
|
<div class="flex flex-col pt-9 md:pt-20">
|
||||||
<div class="mb-4 flex flex-row gap-2">
|
<div class="mb-4 flex flex-row gap-2">
|
||||||
{#each postInfo.labels as label (label.id)}
|
{#each postInfo.labels as label (label.id)}
|
||||||
<Label {label} />
|
<PostLabel {label} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-gray-800 sm:text-4xl md:text-5xl">{postInfo.title}</h1>
|
<h1 class="text-3xl font-bold text-gray-800 sm:text-4xl md:text-5xl">{postInfo.title}</h1>
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<article class="container prose pb-10 prose-gray">
|
<article class="content-container prose pb-10 prose-gray">
|
||||||
{#if state.data}
|
{#if state.data}
|
||||||
<PostContentHeader postInfo={state.data.info} />
|
<PostContentHeader postInfo={state.data.info} />
|
||||||
<div class="max-w-3xl">
|
<div class="max-w-3xl">
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
content="探索 魚之魷魂 SquidSpirit 的所有文章,這裡是您尋找最新技術洞見與實用教學的園地。"
|
content="探索 魚之魷魂 SquidSpirit 的所有文章,這裡是您尋找最新技術洞見與實用教學的園地。"
|
||||||
/>
|
/>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<div class="container pb-10">
|
<div class="content-container pb-10">
|
||||||
<h1 class="py-9 text-center text-3xl font-bold text-gray-800 md:py-20 md:text-5xl">文章</h1>
|
<h1 class="py-9 text-center text-3xl font-bold text-gray-800 md:py-20 md:text-5xl">文章</h1>
|
||||||
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 md:gap-y-8 lg:grid-cols-3">
|
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 md:gap-y-8 lg:grid-cols-3">
|
||||||
{#each state.data ?? [] as postInfo (postInfo.id)}
|
{#each state.data ?? [] as postInfo (postInfo.id)}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { LabelViewModel } from '$lib/post/adapter/presenter/labelViewModel';
|
import type { LabelViewModel } from '$lib/post/adapter/presenter/labelViewModel';
|
||||||
import Label from '$lib/post/framework/ui/Label.svelte';
|
import PostLabel from '$lib/post/framework/ui/PostLabel.svelte';
|
||||||
|
|
||||||
const { labels }: { labels: readonly LabelViewModel[] } = $props();
|
const { labels }: { labels: readonly LabelViewModel[] } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-row gap-x-2">
|
<div class="flex flex-row gap-x-2">
|
||||||
{#each labels.slice(0, 2) as label (label.id)}
|
{#each labels.slice(0, 2) as label (label.id)}
|
||||||
<Label {label} />
|
<PostLabel {label} />
|
||||||
{/each}
|
{/each}
|
||||||
{#if labels.length > 2}
|
{#if labels.length > 2}
|
||||||
<div class="rounded-full bg-gray-200 px-2 py-0.5 text-xs">
|
<div class="rounded-full bg-gray-200 px-2 py-0.5 text-xs">
|
||||||
|
@ -1 +1,5 @@
|
|||||||
<div>Image</div>
|
<script>
|
||||||
|
import ImageManagementPage from '$lib/image/framework/ui/ImageManagementPage.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ImageManagementPage />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user