feat: Upgrade to TailwindCSS 4 & DaisyUI 5 (#263)
Also fixes #251 Reviewed-on: https://codeberg.org/freesewing/freesewing/pulls/263 Co-authored-by: joostdecock <joost@joost.at> Co-committed-by: joostdecock <joost@joost.at>
This commit is contained in:
parent
a2863e5158
commit
44e04a4cef
164 changed files with 2361 additions and 2658 deletions
84
README.md
84
README.md
|
@ -1,39 +1,53 @@
|
|||
<p align='center'><a
|
||||
href="https://www.npmjs.com/package/@freesewing/core"
|
||||
title="@freesewing/core on NPM"
|
||||
><img src="https://img.shields.io/npm/v/@freesewing/core.svg"
|
||||
alt="@freesewing/core on NPM"/>
|
||||
</a><a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img src="https://img.shields.io/npm/l/@freesewing/core.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a><a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
title="Code quality on DeepScan"
|
||||
><img src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="DeepScan grade"
|
||||
></a> <a
|
||||
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen"
|
||||
title="Open issues tagged pkg:aaron"
|
||||
><img src="https://img.shields.io/github/issues/freesewing/freesewing.svg?label=Issues"
|
||||
alt="Open issues"/>
|
||||
</a><a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img src="https://img.shields.io/badge/all_contributors-131-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p><p align='center'><a
|
||||
href="https://discord.freesewing.org"
|
||||
title="Chat with us on Discord"
|
||||
><img src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
|
||||
alt="Chat with us on Discord"/>
|
||||
</a><a
|
||||
href="https://freesewing.org/patrons/join"
|
||||
title="Become a FreeSewing Patron"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||
alt="Become a FreeSewing Patron"/>
|
||||
</a></p>
|
||||
href="https://www.npmjs.com/package/@freesewing/core"
|
||||
title="@freesewing/core on NPM"
|
||||
><img
|
||||
src="https://img.shields.io/npm/v/@freesewing/core.svg"
|
||||
alt="@freesewing/core on NPM"/>
|
||||
</a> <a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img
|
||||
src="https://img.shields.io/npm/l/@freesewing/core.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a> <a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
title="Code quality on DeepScan"
|
||||
><img
|
||||
src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="DeepScan grade"
|
||||
></a> <a
|
||||
href="https://codeberg.org/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen"
|
||||
title="Open issues"
|
||||
><img
|
||||
src="https://img.shields.io/github/issues/freesewing/freesewing.svg?label=Issues"
|
||||
alt="Open issues"/>
|
||||
</a> <a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img
|
||||
src="https://img.shields.io/badge/all_contributors-131-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p>
|
||||
<p align='center'><a
|
||||
href="https://forum.freesewing.eu"
|
||||
title="Join the FreeSewing Forum"
|
||||
><img
|
||||
src="https://img.shields.io/discourse/users?server=https%3A%2F%2Fforum.freesewing.eu&label=Forum&color=%2385d996"
|
||||
alt="Join the FreeSewing Forum"
|
||||
/></a> <a
|
||||
href="https://discord.freesewing.org"
|
||||
title="Chat with us on Discord"
|
||||
><img
|
||||
src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
|
||||
alt="Chat with us on Discord"
|
||||
/></a> <a
|
||||
href="https://freesewing.org/patrons/join"
|
||||
title="Become a FreeSewing Patron"
|
||||
><img
|
||||
src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||
alt="Become a FreeSewing Patron"
|
||||
/></a></p>
|
||||
|
||||
# FreeSewing
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"plugin-mirror": "A FreeSewing plugin to mirror points or paths",
|
||||
"plugin-ringsector": "A FreeSewing plugin to draft a ring sector (think part of a donut)",
|
||||
"plugin-round": "A FreeSewing plugin to round corners",
|
||||
"plugin-path-utils": "A FreeSewing plugin that adds various path helper macros",
|
||||
"plugin-sprinkle": "A FreeSewing plugin to bulk-add snippets to your pattern",
|
||||
"plugin-svgattr": "A FreeSewing plugin to set SVG attributes",
|
||||
"plugin-theme": "A FreeSewing plugin that provides a default theme",
|
||||
|
|
|
@ -1,39 +1,53 @@
|
|||
<p align='center'><a
|
||||
href="https://www.npmjs.com/package/@freesewing/core"
|
||||
title="@freesewing/core on NPM"
|
||||
><img src="https://img.shields.io/npm/v/@freesewing/core.svg"
|
||||
alt="@freesewing/core on NPM"/>
|
||||
</a><a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img src="https://img.shields.io/npm/l/@freesewing/core.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a><a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
title="Code quality on DeepScan"
|
||||
><img src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="DeepScan grade"
|
||||
></a> <a
|
||||
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen"
|
||||
title="Open issues tagged pkg:aaron"
|
||||
><img src="https://img.shields.io/github/issues/freesewing/freesewing.svg?label=Issues"
|
||||
alt="Open issues"/>
|
||||
</a><a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img src="https://img.shields.io/badge/all_contributors-{{ allcontributors }}-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p><p align='center'><a
|
||||
href="https://discord.freesewing.org"
|
||||
title="Chat with us on Discord"
|
||||
><img src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
|
||||
alt="Chat with us on Discord"/>
|
||||
</a><a
|
||||
href="https://freesewing.org/patrons/join"
|
||||
title="Become a FreeSewing Patron"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||
alt="Become a FreeSewing Patron"/>
|
||||
</a></p>
|
||||
href="https://www.npmjs.com/package/@freesewing/core"
|
||||
title="@freesewing/core on NPM"
|
||||
><img
|
||||
src="https://img.shields.io/npm/v/@freesewing/core.svg"
|
||||
alt="@freesewing/core on NPM"/>
|
||||
</a> <a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img
|
||||
src="https://img.shields.io/npm/l/@freesewing/core.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a> <a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
title="Code quality on DeepScan"
|
||||
><img
|
||||
src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="DeepScan grade"
|
||||
></a> <a
|
||||
href="https://codeberg.org/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen"
|
||||
title="Open issues"
|
||||
><img
|
||||
src="https://img.shields.io/github/issues/freesewing/freesewing.svg?label=Issues"
|
||||
alt="Open issues"/>
|
||||
</a> <a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img
|
||||
src="https://img.shields.io/badge/all_contributors-{{ allcontributors }}-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p>
|
||||
<p align='center'><a
|
||||
href="https://forum.freesewing.eu"
|
||||
title="Join the FreeSewing Forum"
|
||||
><img
|
||||
src="https://img.shields.io/discourse/users?server=https%3A%2F%2Fforum.freesewing.eu&label=Forum&color=%2385d996"
|
||||
alt="Join the FreeSewing Forum"
|
||||
/></a> <a
|
||||
href="https://discord.freesewing.org"
|
||||
title="Chat with us on Discord"
|
||||
><img
|
||||
src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
|
||||
alt="Chat with us on Discord"
|
||||
/></a> <a
|
||||
href="https://freesewing.org/patrons/join"
|
||||
title="Become a FreeSewing Patron"
|
||||
><img
|
||||
src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||
alt="Become a FreeSewing Patron"
|
||||
/></a></p>
|
||||
|
||||
# FreeSewing
|
||||
|
||||
|
|
414
package-lock.json
generated
414
package-lock.json
generated
|
@ -31854,6 +31854,257 @@
|
|||
"node": ">=14.16"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.3.tgz",
|
||||
"integrity": "sha512-H/6r6IPFJkCfBJZ2dKZiPJ7Ueb2wbL592+9bQEl2r73qbX6yGnmQVIfiUvDRB2YI0a3PWDrzUwkvQx1XW1bNkA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"enhanced-resolve": "^5.18.1",
|
||||
"jiti": "^2.4.2",
|
||||
"lightningcss": "1.29.2",
|
||||
"tailwindcss": "4.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node/node_modules/tailwindcss": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.3.tgz",
|
||||
"integrity": "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.3.tgz",
|
||||
"integrity": "sha512-t16lpHCU7LBxDe/8dCj9ntyNpXaSTAgxWm1u2XQP5NiIu4KGSyrDJJRlK9hJ4U9yJxx0UKCVI67MJWFNll5mOQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tailwindcss/oxide-android-arm64": "4.1.3",
|
||||
"@tailwindcss/oxide-darwin-arm64": "4.1.3",
|
||||
"@tailwindcss/oxide-darwin-x64": "4.1.3",
|
||||
"@tailwindcss/oxide-freebsd-x64": "4.1.3",
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.3",
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.3",
|
||||
"@tailwindcss/oxide-linux-arm64-musl": "4.1.3",
|
||||
"@tailwindcss/oxide-linux-x64-gnu": "4.1.3",
|
||||
"@tailwindcss/oxide-linux-x64-musl": "4.1.3",
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.3",
|
||||
"@tailwindcss/oxide-win32-x64-msvc": "4.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-android-arm64": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.3.tgz",
|
||||
"integrity": "sha512-cxklKjtNLwFl3mDYw4XpEfBY+G8ssSg9ADL4Wm6//5woi3XGqlxFsnV5Zb6v07dxw1NvEX2uoqsxO/zWQsgR+g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.3.tgz",
|
||||
"integrity": "sha512-mqkf2tLR5VCrjBvuRDwzKNShRu99gCAVMkVsaEOFvv6cCjlEKXRecPu9DEnxp6STk5z+Vlbh1M5zY3nQCXMXhw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.3.tgz",
|
||||
"integrity": "sha512-7sGraGaWzXvCLyxrc7d+CCpUN3fYnkkcso3rCzwUmo/LteAl2ZGCDlGvDD8Y/1D3ngxT8KgDj1DSwOnNewKhmg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.3.tgz",
|
||||
"integrity": "sha512-E2+PbcbzIReaAYZe997wb9rId246yDkCwAakllAWSGqe6VTg9hHle67hfH6ExjpV2LSK/siRzBUs5wVff3RW9w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.3.tgz",
|
||||
"integrity": "sha512-GvfbJ8wjSSjbLFFE3UYz4Eh8i4L6GiEYqCtA8j2Zd2oXriPuom/Ah/64pg/szWycQpzRnbDiJozoxFU2oJZyfg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.3.tgz",
|
||||
"integrity": "sha512-35UkuCWQTeG9BHcBQXndDOrpsnt3Pj9NVIB4CgNiKmpG8GnCNXeMczkUpOoqcOhO6Cc/mM2W7kaQ/MTEENDDXg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.3.tgz",
|
||||
"integrity": "sha512-dm18aQiML5QCj9DQo7wMbt1Z2tl3Giht54uVR87a84X8qRtuXxUqnKQkRDK5B4bCOmcZ580lF9YcoMkbDYTXHQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.3.tgz",
|
||||
"integrity": "sha512-LMdTmGe/NPtGOaOfV2HuO7w07jI3cflPrVq5CXl+2O93DCewADK0uW1ORNAcfu2YxDUS035eY2W38TxrsqngxA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.3.tgz",
|
||||
"integrity": "sha512-aalNWwIi54bbFEizwl1/XpmdDrOaCjRFQRgtbv9slWjmNPuJJTIKPHf5/XXDARc9CneW9FkSTqTbyvNecYAEGw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.3.tgz",
|
||||
"integrity": "sha512-PEj7XR4OGTGoboTIAdXicKuWl4EQIjKHKuR+bFy9oYN7CFZo0eu74+70O4XuERX4yjqVZGAkCdglBODlgqcCXg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.3.tgz",
|
||||
"integrity": "sha512-T8gfxECWDBENotpw3HR9SmNiHC9AOJdxs+woasRZ8Q/J4VHN0OMs7F+4yVNZ9EVN26Wv6mZbK0jv7eHYuLJLwA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/postcss": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.3.tgz",
|
||||
"integrity": "sha512-6s5nJODm98F++QT49qn8xJKHQRamhYHfMi3X7/ltxiSQ9dyRsaFSfFkfaMsanWzf+TMYQtbk8mt5f6cCVXJwfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
"@tailwindcss/node": "4.1.3",
|
||||
"@tailwindcss/oxide": "4.1.3",
|
||||
"postcss": "^8.4.41",
|
||||
"tailwindcss": "4.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/postcss/node_modules/tailwindcss": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.3.tgz",
|
||||
"integrity": "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
|
@ -37530,16 +37781,6 @@
|
|||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-selector-tokenizer": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
|
||||
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"fastparse": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
|
||||
|
@ -37729,15 +37970,6 @@
|
|||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/culori": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
|
||||
"integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-dispatch": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
||||
|
@ -37770,22 +38002,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/daisyui": {
|
||||
"version": "4.12.23",
|
||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.23.tgz",
|
||||
"integrity": "sha512-EM38duvxutJ5PD65lO/AFMpcw+9qEy6XAZrTpzp7WyaPeO/l+F/Qiq0ECHHmFNcFXh5aVoALY4MGrrxtCiaQCQ==",
|
||||
"version": "5.0.19",
|
||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.19.tgz",
|
||||
"integrity": "sha512-vuxloVgdmTnGpA6CFnQyLkXuqPmusHgYZ0L5Qg1pQzAYPUMc0HM2S3brnu7xRnAUq7ZMAqyoV78Fvht7nY2svg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css-selector-tokenizer": "^0.8",
|
||||
"culori": "^3",
|
||||
"picocolors": "^1",
|
||||
"postcss-js": "^4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/daisyui"
|
||||
"url": "https://github.com/saadeghi/daisyui?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
|
@ -38330,15 +38553,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"detect-libc": "bin/detect-libc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node": {
|
||||
|
@ -40693,12 +40913,6 @@
|
|||
"fxparser": "src/cli/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/fastparse": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
|
||||
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
|
||||
|
@ -46450,12 +46664,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.1.tgz",
|
||||
"integrity": "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz",
|
||||
"integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"detect-libc": "^1.0.3"
|
||||
"detect-libc": "^2.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
|
@ -46465,22 +46679,22 @@
|
|||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"lightningcss-darwin-arm64": "1.29.1",
|
||||
"lightningcss-darwin-x64": "1.29.1",
|
||||
"lightningcss-freebsd-x64": "1.29.1",
|
||||
"lightningcss-linux-arm-gnueabihf": "1.29.1",
|
||||
"lightningcss-linux-arm64-gnu": "1.29.1",
|
||||
"lightningcss-linux-arm64-musl": "1.29.1",
|
||||
"lightningcss-linux-x64-gnu": "1.29.1",
|
||||
"lightningcss-linux-x64-musl": "1.29.1",
|
||||
"lightningcss-win32-arm64-msvc": "1.29.1",
|
||||
"lightningcss-win32-x64-msvc": "1.29.1"
|
||||
"lightningcss-darwin-arm64": "1.29.2",
|
||||
"lightningcss-darwin-x64": "1.29.2",
|
||||
"lightningcss-freebsd-x64": "1.29.2",
|
||||
"lightningcss-linux-arm-gnueabihf": "1.29.2",
|
||||
"lightningcss-linux-arm64-gnu": "1.29.2",
|
||||
"lightningcss-linux-arm64-musl": "1.29.2",
|
||||
"lightningcss-linux-x64-gnu": "1.29.2",
|
||||
"lightningcss-linux-x64-musl": "1.29.2",
|
||||
"lightningcss-win32-arm64-msvc": "1.29.2",
|
||||
"lightningcss-win32-x64-msvc": "1.29.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-arm64": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.1.tgz",
|
||||
"integrity": "sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz",
|
||||
"integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -46498,9 +46712,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.1.tgz",
|
||||
"integrity": "sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz",
|
||||
"integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -46518,9 +46732,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-freebsd-x64": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.1.tgz",
|
||||
"integrity": "sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz",
|
||||
"integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -46538,9 +46752,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm-gnueabihf": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.1.tgz",
|
||||
"integrity": "sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz",
|
||||
"integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -46558,9 +46772,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-gnu": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.1.tgz",
|
||||
"integrity": "sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz",
|
||||
"integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -46578,9 +46792,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-musl": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.1.tgz",
|
||||
"integrity": "sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz",
|
||||
"integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -46598,9 +46812,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-gnu": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.1.tgz",
|
||||
"integrity": "sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz",
|
||||
"integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -46618,9 +46832,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-musl": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.1.tgz",
|
||||
"integrity": "sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz",
|
||||
"integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -46638,9 +46852,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-arm64-msvc": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.1.tgz",
|
||||
"integrity": "sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz",
|
||||
"integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -46658,9 +46872,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-x64-msvc": {
|
||||
"version": "1.29.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.1.tgz",
|
||||
"integrity": "sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==",
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz",
|
||||
"integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -58329,15 +58543,6 @@
|
|||
"@img/sharp-win32-x64": "0.33.5"
|
||||
}
|
||||
},
|
||||
"node_modules/sharp/node_modules/detect-libc": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/sharp/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
|
@ -70571,7 +70776,6 @@
|
|||
"@mdx-js/react": "^3.0.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"clsx": "^2.0.0",
|
||||
"daisyui": "^4.12.23",
|
||||
"lodash": "^4.17.21",
|
||||
"postcss": "^8.4.47",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
|
@ -70579,12 +70783,14 @@
|
|||
"react-dom": "^19.0.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"remark-smartypants": "^3.0.2",
|
||||
"tailwindcss": "^3.4.14"
|
||||
"tailwindcss": "^4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-syntax-import-attributes": "^7.25.6",
|
||||
"@docusaurus/module-type-aliases": "^3.7.0",
|
||||
"@docusaurus/types": "^3.7.0",
|
||||
"@tailwindcss/postcss": "^4.1.3",
|
||||
"daisyui": "^5.0.19",
|
||||
"glob": "^11.0.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"yaml-loader": "^0.8.1"
|
||||
|
@ -70665,6 +70871,12 @@
|
|||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"sites/org/node_modules/tailwindcss": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.3.tgz",
|
||||
"integrity": "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,16 +102,16 @@ export const Apikeys = ({ Link = false }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-2 tw-items-center tw-justify-between tw-mb-4">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-2 tw:items-center tw:justify-between tw:mb-4">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-error"
|
||||
className="tw:daisy-btn tw:daisy-btn-error"
|
||||
onClick={removeSelectedApikeys}
|
||||
disabled={count < 1}
|
||||
>
|
||||
<TrashIcon /> {count} API Keys
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-capitalize tw-w-full md:tw-w-auto hover:tw-text-primary-content"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize tw:w-full tw:md:w-auto tw:hover:text-primary-content"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper keepOpenOnClick>
|
||||
|
@ -125,13 +125,13 @@ export const Apikeys = ({ Link = false }) => {
|
|||
</button>
|
||||
</div>
|
||||
<TableWrapper>
|
||||
<table className="tw-table tw-table-auto">
|
||||
<thead className="tw-border tw-border-base-300 tw-border-b-2 tw-border-t-0 tw-border-x-0">
|
||||
<table className="tw:table tw:table-auto">
|
||||
<thead className="tw:border tw:border-base-300 tw:border-b-2 tw:border-t-0 tw:border-x-0">
|
||||
<tr className="">
|
||||
<th className="">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={toggleAll}
|
||||
checked={apikeys.length === count}
|
||||
/>
|
||||
|
@ -139,13 +139,13 @@ export const Apikeys = ({ Link = false }) => {
|
|||
{Object.keys(fields).map((field) => (
|
||||
<th key={field}>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-link tw-capitalize tw-px-0 underline tw-hover:decoration-4 tw-decoration-2 tw-text-secondary"
|
||||
className="tw:daisy-btn tw:daisy-btn-link tw:capitalize tw:px-0 underline tw:hover:decoration-4 tw:decoration-2 tw:text-secondary"
|
||||
onClick={() => (order === field ? setDesc(!desc) : setOrder(field))}
|
||||
>
|
||||
{fields[field]}{' '}
|
||||
<RightIcon
|
||||
stroke={3}
|
||||
className={`tw-w-4 tw-h-4 ${desc ? 'tw--' : 'tw-'}rotate-90 ${order === field ? '' : 'tw-opacity-0'}`}
|
||||
className={`tw:w-4 tw:h-4 ${desc ? 'tw:-' : 'tw:'}rotate-90 ${order === field ? '' : 'tw:opacity-0'}`}
|
||||
/>
|
||||
</button>
|
||||
</th>
|
||||
|
@ -155,23 +155,23 @@ export const Apikeys = ({ Link = false }) => {
|
|||
<tbody>
|
||||
{orderBy(apikeys, order, desc ? 'desc' : 'asc').map((apikey, i) => (
|
||||
<tr key={i}>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selection[apikey.id] ? true : false}
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={() => toggle(apikey.id)}
|
||||
/>
|
||||
</td>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<Uuid uuid={apikey.id} label="Key" />
|
||||
</td>
|
||||
{Object.keys(fields)
|
||||
.slice(1, 4)
|
||||
.map((field) => (
|
||||
<td key={field} className="tw-text-base tw-font-medium">
|
||||
<td key={field} className="tw:text-base tw:font-medium">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-link tw-text-secondary hover:tw-decoration-4"
|
||||
className="tw:daisy-btn tw:daisy-btn-link tw:text-secondary tw:hover:decoration-4"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper>
|
||||
|
@ -184,8 +184,8 @@ export const Apikeys = ({ Link = false }) => {
|
|||
</button>
|
||||
</td>
|
||||
))}
|
||||
<td className="tw-text-base tw-font-medium">{shortDate(apikey.createdAt)}</td>
|
||||
<td className="tw-text-base tw-font-medium">{shortDate(apikey.expiresAt)}</td>
|
||||
<td className="tw:text-base tw:font-medium">{shortDate(apikey.createdAt)}</td>
|
||||
<td className="tw:text-base tw:font-medium">{shortDate(apikey.expiresAt)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
@ -197,10 +197,10 @@ export const Apikeys = ({ Link = false }) => {
|
|||
|
||||
const ApiKey = ({ apikey }) => (
|
||||
<>
|
||||
<h2 className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<h2 className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
API Key <Uuid uuid={apikey.id} />
|
||||
</h2>
|
||||
<ul className="tw-list tw-list-disc tw-ml-4">
|
||||
<ul className="tw:list tw:list-disc tw:ml-4">
|
||||
{Object.entries(fields).map(([key, label]) => (
|
||||
<li key={key}>
|
||||
{label}: <b>{apikey[key]}</b>
|
||||
|
@ -248,7 +248,7 @@ const NewApikey = ({ onCreate = false }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<h2>New API key {apikey ? `: ${apikey.name}` : ''}</h2>
|
||||
{apikey ? (
|
||||
<ShowNewApikey {...{ apikey }} />
|
||||
|
@ -269,7 +269,7 @@ const NewApikey = ({ onCreate = false }) => {
|
|||
list={levels.map((l) => ({
|
||||
val: l,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-w-full tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:w-full tw:justify-between">
|
||||
<span>{apikeyLevels[l]}</span>
|
||||
<NumberCircle nr={l} color="secondary" />
|
||||
</div>
|
||||
|
@ -278,9 +278,9 @@ const NewApikey = ({ onCreate = false }) => {
|
|||
current={level}
|
||||
update={setLevel}
|
||||
/>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-w-full tw-my-8">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:w-full tw:my-8">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-capitalize tw-w-full md:tw-w-auto"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize tw:w-full tw:md:w-auto"
|
||||
disabled={name.length < 1}
|
||||
onClick={createKey}
|
||||
>
|
||||
|
@ -295,18 +295,18 @@ const NewApikey = ({ onCreate = false }) => {
|
|||
|
||||
const ShowNewApikey = ({ apikey }) => (
|
||||
<div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-2 tw-items-center tw-mb-2">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-2 tw:items-center tw:mb-2">
|
||||
<KeyVal k="name" val={apikey.name} color="secondary" />
|
||||
<KeyVal k="level" val={apikey.level} color="secondary" />
|
||||
<KeyVal k="created" val={<TimeAgo iso={apikey.createdAt} />} color="secondary" />
|
||||
<KeyVal k="expires" val={<TimeToGo iso={apikey.expiresAt} />} color="secondary" />
|
||||
</div>
|
||||
<h6 className="tw-flex tw-flex-row tw-items-center">
|
||||
<h6 className="tw:flex tw:flex-row tw:items-center">
|
||||
Key
|
||||
<CopyToClipboardButton sup content={apikey.key} label="API key ID" />
|
||||
</h6>
|
||||
<pre>{apikey.key}</pre>
|
||||
<h6 className="tw-flex tw-flex-row tw-items-center">
|
||||
<h6 className="tw:flex tw:flex-row tw:items-center">
|
||||
Secret
|
||||
<CopyToClipboardButton sup content={apikey.secret} label="API key secret" />
|
||||
</h6>
|
||||
|
@ -330,7 +330,7 @@ const ExpiryPicker = ({ expires, setExpires }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<FormControl
|
||||
label="Key Expiry"
|
||||
labelBL={shortDate(expires)}
|
||||
|
@ -341,7 +341,7 @@ const ExpiryPicker = ({ expires, setExpires }) => {
|
|||
min="1"
|
||||
max={731}
|
||||
value={days}
|
||||
className="tw-daisy-range tw-daisy-range-secondary tw-w-full"
|
||||
className="tw:daisy-range tw:daisy-range-secondary tw:w-full"
|
||||
onChange={update}
|
||||
/>
|
||||
</FormControl>
|
||||
|
|
|
@ -51,12 +51,12 @@ export const Avatar = ({ welcome = false, Link = false }) => {
|
|||
const nextHref = '/docs/about/guide'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{!welcome || img !== false ? (
|
||||
<img
|
||||
alt="img"
|
||||
src={img || cloudflareImageUrl({ id: `uid-${account.ihash}`, variant: 'public' })}
|
||||
className="tw-shadow tw-mb-4"
|
||||
className="tw:shadow tw:mb-4"
|
||||
/>
|
||||
) : null}
|
||||
<PassiveImageInput
|
||||
|
@ -73,17 +73,17 @@ export const Avatar = ({ welcome = false, Link = false }) => {
|
|||
<SaveIcon />
|
||||
Save
|
||||
</IconButton>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[account.control].length > 0 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-progress tw-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:progress tw:progress-primary tw:w-full tw:mt-12"
|
||||
value={700 / welcomeSteps[account.control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
7 / {welcomeSteps[account.control].length}
|
||||
</span>
|
||||
<WelcomeIcons
|
||||
|
@ -96,9 +96,9 @@ export const Avatar = ({ welcome = false, Link = false }) => {
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto mt-8"
|
||||
onClick={save}
|
||||
>
|
||||
<SaveIcon /> Save Avatar
|
||||
|
|
|
@ -51,12 +51,12 @@ export const Bio = ({ welcome = false, Link = false }) => {
|
|||
: '/docs/about/guide'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<h6>Tell people a little bit about yourself.</h6>
|
||||
<MarkdownInput id="account-bio" label="Bio" update={setBio} current={bio} placeholder="Bio" />
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto tw:mt-8"
|
||||
onClick={save}
|
||||
>
|
||||
<SaveIcon /> Save Bio
|
||||
|
@ -65,17 +65,17 @@ export const Bio = ({ welcome = false, Link = false }) => {
|
|||
|
||||
{welcome ? (
|
||||
<>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[account.control].length > 0 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-daisy-progress tw-daisy-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:daisy-progress tw:daisy-progress-primary tw:w-full tw:mt-12"
|
||||
value={600 / welcomeSteps[account.control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
6 / {welcomeSteps[account.control].length}
|
||||
</span>
|
||||
<WelcomeIcons
|
||||
|
|
|
@ -88,10 +88,10 @@ export const Bookmarks = () => {
|
|||
for (const type in types) perType[type] = bookmarks.filter((b) => b.type === type)
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<p className="tw-text-center md:tw-text-right">
|
||||
<div className="tw:w-full">
|
||||
<p className="tw:text-center tw:md:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-capitalize tw-w-full md:tw-w-auto hover:tw-text-primary-content hover:tw-no-underline"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize tw:w-full tw:md:w-auto tw:hover:text-primary-content tw:hover:no-underline"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper
|
||||
|
@ -100,7 +100,7 @@ export const Bookmarks = () => {
|
|||
slideFrom="right"
|
||||
keepOpenOnClick
|
||||
>
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<h2>New Bookmark</h2>
|
||||
<NewBookmark onCreated={() => setRefresh(refresh + 1)} />
|
||||
</div>
|
||||
|
@ -114,7 +114,7 @@ export const Bookmarks = () => {
|
|||
</p>
|
||||
{bookmarks.length > 0 ? (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-error"
|
||||
className="tw:daisy-btn tw:daisy-btn-error"
|
||||
onClick={removeSelectedBookmarks}
|
||||
disabled={selCount < 1}
|
||||
>
|
||||
|
@ -125,18 +125,18 @@ export const Bookmarks = () => {
|
|||
perType[type].length > 0 ? (
|
||||
<Fragment key={type}>
|
||||
<h2>{title}</h2>
|
||||
<table className="tw-table tw-w-full">
|
||||
<thead className="tw-border tw-border-base-300 tw-border-b-2 tw-border-t-0 tw-border-x-0">
|
||||
<table className="tw:table tw:w-full">
|
||||
<thead className="tw:border tw:border-base-300 tw:border-b-2 tw:border-t-0 tw:border-x-0">
|
||||
<tr>
|
||||
<th className="tw-text-base-300 tw-text-base tw-text-left tw-w-8">
|
||||
<th className="tw:text-base-300 tw:text-base tw:text-left tw:w-8">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={toggleSelectAll}
|
||||
checked={bookmarks.length === selCount}
|
||||
/>
|
||||
</th>
|
||||
<th className="tw-w-1/2">Title</th>
|
||||
<th className="tw:w-1/2">Title</th>
|
||||
<th>Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -145,16 +145,16 @@ export const Bookmarks = () => {
|
|||
.filter((bookmark) => bookmark.type === type)
|
||||
.map((bookmark, i) => (
|
||||
<tr key={i}>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selected[bookmark.id] ? true : false}
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={() => toggleSelect(bookmark.id)}
|
||||
/>
|
||||
</td>
|
||||
<td className="tw-text-base tw-font-medium">{bookmark.title}</td>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">{bookmark.title}</td>
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<WebLink href={bookmark.url}>
|
||||
{bookmark.url.length > 30
|
||||
? bookmark.url.slice(0, 30) + '...'
|
||||
|
@ -210,7 +210,7 @@ export const NewBookmark = ({ onCreated = false }) => {
|
|||
|
||||
// Render the form
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<StringInput
|
||||
id="bookmark-title"
|
||||
label="Title"
|
||||
|
@ -229,9 +229,9 @@ export const NewBookmark = ({ onCreated = false }) => {
|
|||
valid={(val) => val.length > 0}
|
||||
placeholder={'https://freesewing.org/account'}
|
||||
/>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-w-full tw-my-8">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:w-full tw:my-8">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-grow tw-capitalize"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:grow tw:capitalize"
|
||||
disabled={!(title.length > 0 && url.length > 0)}
|
||||
onClick={createBookmark}
|
||||
>
|
||||
|
@ -256,7 +256,7 @@ export const BookmarkButton = ({ slug, type, title }) => {
|
|||
|
||||
return (
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline ${horFlexClasses}`}
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper flex="col" justify="top lg:justify-center" slideFrom="right">
|
||||
|
@ -305,10 +305,10 @@ export const CreateBookmark = ({ type, title, slug }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-mt-12">
|
||||
<div className="tw:mt-12">
|
||||
<h2>New bookmark</h2>
|
||||
<StringInput label="Title" current={name} update={setName} valid={notEmpty} labelBL={url} />
|
||||
<button className="tw-daisy-btn tw-daisy-btn-primary tw-w-full tw-mt-4" onClick={bookmark}>
|
||||
<button className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:mt-4" onClick={bookmark}>
|
||||
Create bookmark
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -70,19 +70,19 @@ export const Compare = ({ welcome = false }) => {
|
|||
: '/docs/about/guide'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<ListInput
|
||||
id="account-compare"
|
||||
label="Are you comfortable with your measurements sets being compared?"
|
||||
list={['yes', 'no'].map((val) => ({
|
||||
val,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-w-full tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:w-full tw:justify-between">
|
||||
<span>{strings[val].title}</span>
|
||||
{val === 'yes' ? (
|
||||
<OkIcon className="tw-w-8 h-8 tw-text-success" stroke={4} />
|
||||
<OkIcon className="tw:w-8 h-8 tw:text-success" stroke={4} />
|
||||
) : (
|
||||
<NoIcon className="tw-w-8 h-8 tw-text-error" stroke={3} />
|
||||
<NoIcon className="tw:w-8 h-8 tw:text-error" stroke={3} />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
|
@ -93,17 +93,17 @@ export const Compare = ({ welcome = false }) => {
|
|||
/>
|
||||
{welcome ? (
|
||||
<>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[account?.control].length > 0 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-daisy-progress tw-daisy-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:daisy-progress tw:daisy-progress-primary tw:w-full tw:mt-12"
|
||||
value={400 / welcomeSteps[account?.control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
4 / {welcomeSteps[account?.control].length}
|
||||
</span>
|
||||
<WelcomeIcons
|
||||
|
|
|
@ -86,16 +86,16 @@ export const Consent = ({ signUp = false, Link = false, title = false }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full mdx">
|
||||
{title ? <h2 className="tw-text-4xl">Privacy Matters</h2> : null}
|
||||
<div className="tw:w-full mdx">
|
||||
{title ? <h2 className="tw:text-4xl">Privacy Matters</h2> : null}
|
||||
{text.intro}
|
||||
<h5 className="tw-mt-8">Do you give your consent to process your account data?</h5>
|
||||
<h5 className="tw:mt-8">Do you give your consent to process your account data?</h5>
|
||||
{text.account}
|
||||
{consent1 ? (
|
||||
<Checkbox value={consent1} setter={setConsent1} label="Yes, I do" />
|
||||
) : (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-lg tw-w-full tw-mt-4"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-lg tw:w-full tw:mt-4"
|
||||
onClick={() => setConsent1(!consent1)}
|
||||
>
|
||||
Click here to give your consent
|
||||
|
@ -103,7 +103,7 @@ export const Consent = ({ signUp = false, Link = false, title = false }) => {
|
|||
)}
|
||||
{consent1 ? (
|
||||
<>
|
||||
<h5 className="tw-mt-8">
|
||||
<h5 className="tw:mt-8">
|
||||
Do you give your consent to share your anonymized measurements
|
||||
</h5>
|
||||
<Checkbox
|
||||
|
@ -116,19 +116,19 @@ export const Consent = ({ signUp = false, Link = false, title = false }) => {
|
|||
) : null}
|
||||
{!consent1 && <Popout warning>This consent is required for a FreeSewing account.</Popout>}
|
||||
{consent1 ? (
|
||||
<button className="tw-daisy-btn tw-daisy-btn-primary tw-w-full tw-mt-4" onClick={update}>
|
||||
<button className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:mt-4" onClick={update}>
|
||||
{signUp ? 'Create Account' : 'Save'}
|
||||
</button>
|
||||
) : signUp ? null : (
|
||||
<button
|
||||
className="tw-daisy-btn tw-mt-4 tw-capitalize tw-w-full tw-daisy-btn-error"
|
||||
className="tw:daisy-btn tw:mt-4 tw:capitalize tw:w-full tw:daisy-btn-error"
|
||||
onClick={removeAccount}
|
||||
>
|
||||
Remove your account
|
||||
</button>
|
||||
)}
|
||||
<p className="tw-text-center tw-opacity-50 tw-mt-12">
|
||||
<Link href="/docs/about/privacy" className="hover:tw-text-secondary tw-underline">
|
||||
<p className="tw:text-center tw:opacity-50 tw:mt-12">
|
||||
<Link href="/docs/about/privacy" className="tw:hover:text-secondary tw:underline">
|
||||
FreeSewing Privacy Notice
|
||||
</Link>
|
||||
</p>
|
||||
|
@ -138,19 +138,19 @@ export const Consent = ({ signUp = false, Link = false, title = false }) => {
|
|||
|
||||
const Checkbox = ({ value, setter, label, children = null }) => (
|
||||
<div
|
||||
className={`tw-form-control tw-p-4 hover:tw-cursor-pointer tw-rounded tw-border-l-8 tw-my-2
|
||||
${value ? 'tw-border-success tw-bg-success/30' : 'tw-border-error tw-bg-error/30'}
|
||||
btw-g-opacity-10 tw-shadow`}
|
||||
className={`tw:form-control tw:p-4 tw:hover:cursor-pointer tw:rounded tw:border-l-8 tw:my-2
|
||||
${value ? 'tw:border-success tw:bg-success/30' : 'tw:border-error tw:bg-error/30'}
|
||||
btw:g-opacity-10 tw:shadow`}
|
||||
onClick={() => setter(value ? false : true)}
|
||||
>
|
||||
<div className="tw-form-control tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<div className="tw:form-control tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="tw-daisy-checkbox"
|
||||
className="tw:daisy-checkbox"
|
||||
checked={value ? 'checked' : ''}
|
||||
onChange={() => setter(value ? false : true)}
|
||||
/>
|
||||
<span className="tw-label-text">{label}</span>
|
||||
<span className="tw:label-text">{label}</span>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
@ -174,7 +174,7 @@ const text = {
|
|||
</>
|
||||
),
|
||||
account: (
|
||||
<div className="tw-border-l-4 tw-ml-1 tw-pl-4 tw-my-2 tw-opacity-80">
|
||||
<div className="tw:border-l-4 tw:ml-1 tw:pl-4 tw:my-2 tw:opacity-80">
|
||||
<h6>What is account data?</h6>
|
||||
<p>
|
||||
Your <b>email address</b>, <b>username</b>, and <b>password</b>, and any <b>measurements</b>{' '}
|
||||
|
@ -194,7 +194,7 @@ const text = {
|
|||
<p>
|
||||
<b>No</b>, never.
|
||||
</p>
|
||||
<p className="tw-text-sm tw-italic">
|
||||
<p className="tw:text-sm tw:italic">
|
||||
Note: Freesewing publishes anonymized measurements as open data for scientific research. You
|
||||
have the right to object to this.
|
||||
</p>
|
||||
|
|
|
@ -52,14 +52,14 @@ export const Control = ({ welcome = false }) => {
|
|||
: false
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<ListInput
|
||||
id="account-control"
|
||||
label="What user experience do you prefer?"
|
||||
list={[1, 2, 3, 4, 5].map((val) => ({
|
||||
val,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-w-full tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:w-full tw:justify-between">
|
||||
<span>{controlDesc[val].title}</span>
|
||||
<ControlScore control={val} />
|
||||
</div>
|
||||
|
@ -71,17 +71,17 @@ export const Control = ({ welcome = false }) => {
|
|||
/>
|
||||
{welcome ? (
|
||||
<>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[control].length > 1 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-daisy-progress tw-daisy-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:daisy-progress tw:daisy-progress-primary tw:w-full tw:mt-12"
|
||||
value={100 / welcomeSteps[control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
1 / {welcomeSteps[control].length}
|
||||
</span>
|
||||
<WelcomeIcons done={[]} todo={welcomeSteps[control].slice(1)} current="" />
|
||||
|
|
|
@ -51,7 +51,7 @@ export const Email = ({ welcome = false, Link = false }) => {
|
|||
const valid = (validateEmail(email) && validateTld(email)) || false
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{changed ? (
|
||||
<Popout note>
|
||||
<h3>Please confirm this change</h3>
|
||||
|
@ -72,9 +72,9 @@ export const Email = ({ welcome = false, Link = false }) => {
|
|||
original={account.email}
|
||||
valid={() => valid}
|
||||
/>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto tw:mt-8"
|
||||
onClick={save}
|
||||
disabled={!valid || email.toLowerCase() === account.email}
|
||||
>
|
||||
|
@ -151,7 +151,7 @@ export const EmailChangeConfirmation = ({ onSuccess = false }) => {
|
|||
return (
|
||||
<>
|
||||
<h1>One moment pleae</h1>
|
||||
<Spinner className="tw-w-8 tw-h-8 tw-m-auto tw-animate-spin" />
|
||||
<Spinner className="tw:w-8 tw:h-8 tw:m-auto tw:animate-spin" />
|
||||
</>
|
||||
)
|
||||
|
||||
|
|
|
@ -34,11 +34,11 @@ export const Export = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-max-w-xl">
|
||||
<div className="tw:max-w-xl">
|
||||
{link ? (
|
||||
<Popout link>
|
||||
<h5>Your data was exported and is available for download at the following location:</h5>
|
||||
<p className="tw-text-lg">
|
||||
<p className="tw:text-lg">
|
||||
<WebLink href={link}>{link}</WebLink>
|
||||
</p>
|
||||
</Popout>
|
||||
|
|
|
@ -34,7 +34,7 @@ export const Github = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<StringInput
|
||||
id="account-github-email"
|
||||
label="GitHub Email Address"
|
||||
|
@ -51,9 +51,9 @@ export const Github = () => {
|
|||
valid={(val) => val.length > 0}
|
||||
placeholder={'joostdecock'}
|
||||
/>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto tw:mt-8"
|
||||
onClick={save}
|
||||
>
|
||||
<SaveIcon /> Save
|
||||
|
|
|
@ -62,7 +62,7 @@ export const ImportSet = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<FileInput
|
||||
label="Measurements file (YAML / JSON)"
|
||||
update={uploadSet}
|
||||
|
|
|
@ -34,7 +34,7 @@ export const Instagram = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<StringInput
|
||||
id="account-github-email"
|
||||
label="GitHub Email Address"
|
||||
|
@ -51,9 +51,9 @@ export const Instagram = () => {
|
|||
valid={(val) => val.length > 0}
|
||||
placeholder={'joostdecock'}
|
||||
/>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto tw:mt-8"
|
||||
onClick={save}
|
||||
>
|
||||
<SaveIcon /> Save
|
||||
|
|
|
@ -72,10 +72,10 @@ const itemIcons = {
|
|||
reddit: <RedditIcon />,
|
||||
}
|
||||
|
||||
const btnClasses = 'tw-daisy-btn tw-capitalize tw-flex tw-flex-row tw-justify-between'
|
||||
const btnClasses = 'tw:daisy-btn tw:capitalize tw:flex tw:flex-row tw:justify-between'
|
||||
const itemClasses =
|
||||
'tw-flex tw-flex-row tw-items-center tw-justify-between tw-bg-opacity-10 tw-p-2 tw-px-4 tw-rounded tw-mb-1'
|
||||
const linkClasses = `hover:tw-bg-secondary hover:tw-bg-opacity-10 tw-max-w-md hover:tw-no-underline`
|
||||
'tw:flex tw:flex-row tw:items-center tw:justify-between tw:p-2 tw:px-4 tw:rounded tw:mb-1'
|
||||
const linkClasses = `tw:hover:bg-secondary/10 tw:max-w-md tw:hover:no-underline tw:text-base-content no-hover-decoration`
|
||||
|
||||
const titles = {
|
||||
apikeys: 'API Keys',
|
||||
|
@ -142,7 +142,7 @@ export const Links = ({ Link = false }) => {
|
|||
img: (
|
||||
<img
|
||||
src={cloudflareImageUrl({ type: 'sq100', id: `uid-${account.ihash}` })}
|
||||
className="tw-w-8 tw-h-8 tw-aspect-square tw-rounded-full shadow"
|
||||
className="tw:w-8 tw:h-8 tw:aspect-square tw:rounded-full shadow"
|
||||
/>
|
||||
),
|
||||
units: account.imperial ? 'Imperial' : 'Metric',
|
||||
|
@ -158,14 +158,14 @@ export const Links = ({ Link = false }) => {
|
|||
(i) => i !== 'github'
|
||||
))
|
||||
itemPreviews[social] = account.data[social] || (
|
||||
<NoIcon className="tw-text-base-content tw-w-6 tw-h-6" stroke={2} />
|
||||
<NoIcon className="tw:text-base-content tw:w-6 tw:h-6" stroke={2} />
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw-grid tw-grid-cols-1 xl:tw-grid-cols-2 tw-gap-4 tw-mb-8">
|
||||
<div className="tw:w-full">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:xl:grid-cols-2 tw:gap-4 tw:mb-8">
|
||||
<div>
|
||||
<h4 className="tw-my-2">Your Data</h4>
|
||||
<h4 className="tw:my-2">Your Data</h4>
|
||||
{Object.keys(controlConfig.account.fields.data).map((item) =>
|
||||
controlConfig.flat[item] > control ? null : (
|
||||
<Link
|
||||
|
@ -174,11 +174,11 @@ export const Links = ({ Link = false }) => {
|
|||
href={`/account/data/${item}/`}
|
||||
className={`${itemClasses} ${linkClasses}`}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium tw:text-base-content">
|
||||
{itemIcons[item]}
|
||||
{titles[item] ? titles[item] : capitalize(item)}
|
||||
</div>
|
||||
<div>{itemPreviews[item]}</div>
|
||||
<div className="tw:text-base-content">{itemPreviews[item]}</div>
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
|
@ -186,7 +186,7 @@ export const Links = ({ Link = false }) => {
|
|||
|
||||
{control > 1 && (
|
||||
<div>
|
||||
<h4 className="tw-my-2">About You</h4>
|
||||
<h4 className="tw:my-2">About You</h4>
|
||||
{Object.keys(controlConfig.account.fields.info).map((item) =>
|
||||
controlConfig.flat[item] > control ? null : (
|
||||
<Link
|
||||
|
@ -195,23 +195,23 @@ export const Links = ({ Link = false }) => {
|
|||
href={`/account/about/${item === 'img' ? 'avatar' : item}/`}
|
||||
className={`${itemClasses} ${linkClasses}`}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium tw:text-base-content">
|
||||
{itemIcons[item]}
|
||||
{titles[item] ? titles[item] : capitalize(item)}
|
||||
</div>
|
||||
<div>{itemPreviews[item]}</div>
|
||||
<div className="tw:text-base-content">{itemPreviews[item]}</div>
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
<div className={`${itemClasses} tw-opacity-60 tw-max-w-md`}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className={`${itemClasses} tw:opacity-60 tw:max-w-md`}>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium">
|
||||
<OkIcon stroke={3} />
|
||||
<span>Role</span>
|
||||
</div>
|
||||
<div className="tw-capitalize">{account.role}</div>
|
||||
<div className="tw:capitalize">{account.role}</div>
|
||||
</div>
|
||||
<div className={`${itemClasses} tw-opacity-60 tw-max-w-md`}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className={`${itemClasses} tw:opacity-60 tw:max-w-md`}>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium">
|
||||
<FingerprintIcon />
|
||||
<span>ID</span>
|
||||
</div>
|
||||
|
@ -221,7 +221,7 @@ export const Links = ({ Link = false }) => {
|
|||
)}
|
||||
|
||||
<div>
|
||||
<h4 className="tw-my-2">Preferences</h4>
|
||||
<h4 className="tw:my-2">Preferences</h4>
|
||||
{Object.keys(controlConfig.account.fields.settings).map((item) =>
|
||||
controlConfig.flat[item] > control ? null : (
|
||||
<Link
|
||||
|
@ -230,11 +230,11 @@ export const Links = ({ Link = false }) => {
|
|||
href={`/account/preferences/${item}/`}
|
||||
className={`${itemClasses} ${linkClasses}`}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium tw:text-base-content">
|
||||
{itemIcons[item]}
|
||||
{titles[item] ? titles[item] : capitalize(item)}
|
||||
</div>
|
||||
<div>{itemPreviews[item]}</div>
|
||||
<div className="tw:text-base-content">{itemPreviews[item]}</div>
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
|
@ -242,7 +242,7 @@ export const Links = ({ Link = false }) => {
|
|||
|
||||
{control > 2 && (
|
||||
<div>
|
||||
<h4 className="tw-my-2">Linked Identities</h4>
|
||||
<h4 className="tw:my-2">Linked Identities</h4>
|
||||
{Object.keys(controlConfig.account.fields.identities).map((item) =>
|
||||
controlConfig.flat[item] > control ? null : (
|
||||
<Link
|
||||
|
@ -251,11 +251,11 @@ export const Links = ({ Link = false }) => {
|
|||
href={`/account/social/${item}/`}
|
||||
className={`${itemClasses} ${linkClasses}`}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium tw:text-base-content">
|
||||
{itemIcons[item]}
|
||||
{titles[item] ? titles[item] : capitalize(item)}
|
||||
</div>
|
||||
<div>{itemPreviews[item]}</div>
|
||||
<div className="tw:text-base-content">{itemPreviews[item]}</div>
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
|
@ -264,7 +264,7 @@ export const Links = ({ Link = false }) => {
|
|||
|
||||
{control > 1 && (
|
||||
<div>
|
||||
<h4 className="tw-my-2">Security</h4>
|
||||
<h4 className="tw:my-2">Security</h4>
|
||||
{Object.keys(controlConfig.account.fields.security).map((item) =>
|
||||
controlConfig.flat[item] > control ? null : (
|
||||
<Link
|
||||
|
@ -273,11 +273,11 @@ export const Links = ({ Link = false }) => {
|
|||
href={`/account/security/${item}/`}
|
||||
className={`${itemClasses} ${linkClasses}`}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-3 tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-3 tw:font-medium tw:text-base-content">
|
||||
{itemIcons[item]}
|
||||
{titles[item] ? titles[item] : capitalize(item)}
|
||||
</div>
|
||||
<div>{itemPreviews[item]}</div>
|
||||
<div className="tw:text-base-content">{itemPreviews[item]}</div>
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
|
@ -286,15 +286,15 @@ export const Links = ({ Link = false }) => {
|
|||
|
||||
{control > 1 && (
|
||||
<div>
|
||||
<h4 className="tw-my-2">Actions</h4>
|
||||
<h4 className="tw:my-2">Actions</h4>
|
||||
{control > 2 && (
|
||||
<Link
|
||||
className={`${itemClasses} ${linkClasses}`}
|
||||
title="Import data"
|
||||
href="/account/actions/import/"
|
||||
>
|
||||
<UploadIcon />
|
||||
<span className="tw-font-medium">Import data</span>
|
||||
<UploadIcon className="tw:w-6 tw:h-6 tw:text-base-content" />
|
||||
<span className="tw:font-medium tw:text-base-content">Import data</span>
|
||||
</Link>
|
||||
)}
|
||||
{control > 2 && (
|
||||
|
@ -303,8 +303,8 @@ export const Links = ({ Link = false }) => {
|
|||
title="Export your data"
|
||||
href="/account/actions/export/"
|
||||
>
|
||||
<DownloadIcon />
|
||||
<span className="tw-font-medium">Export your data</span>
|
||||
<DownloadIcon className="tw:w-6 tw:h-6 tw:text-base-content" />
|
||||
<span className="tw:font-medium tw:text-base-content">Export your data</span>
|
||||
</Link>
|
||||
)}
|
||||
{control > 2 && (
|
||||
|
@ -313,8 +313,8 @@ export const Links = ({ Link = false }) => {
|
|||
title="Reload account data"
|
||||
href="/account/actions/reload/"
|
||||
>
|
||||
<ReloadIcon />
|
||||
<span className="tw-font-medium">Reload account data</span>
|
||||
<ReloadIcon className="tw:w-6 tw:h-6 tw:text-base-content" />
|
||||
<span className="tw:font-medium tw:text-base-content">Reload account data</span>
|
||||
</Link>
|
||||
)}
|
||||
{control > 3 && (
|
||||
|
@ -323,8 +323,10 @@ export const Links = ({ Link = false }) => {
|
|||
title="Restrict processing of your data"
|
||||
href="/account/actions/restrict/"
|
||||
>
|
||||
<CloseIcon className="tw-w-6 tw-h-6 tw-text-warning" stroke={3} />
|
||||
<span className="tw-font-medium">Restrict processing of your data</span>
|
||||
<CloseIcon className="tw:w-6 tw:h-6 tw:text-warning" stroke={3} />
|
||||
<span className="tw:font-medium tw:text-base-content">
|
||||
Restrict processing of your data
|
||||
</span>
|
||||
</Link>
|
||||
)}
|
||||
<Link
|
||||
|
@ -332,28 +334,31 @@ export const Links = ({ Link = false }) => {
|
|||
title="Remove your account"
|
||||
href="/account/actions/remove/"
|
||||
>
|
||||
<TrashIcon className="tw-w-6 tw-h-6 tw-text-warning" />
|
||||
<span className="tw-font-medium">Remove your account</span>
|
||||
<TrashIcon className="tw:w-6 tw:h-6 tw:text-warning" />
|
||||
<span className="tw:font-medium tw:text-base-content">Remove your account</span>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-2 md:tw-gap-4 tw-justify-end">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-2 tw:md:gap-4 tw:justify-end">
|
||||
{account.role === 'admin' && (
|
||||
<Link className={`${btnClasses} tw-daisy-btn-accent md:tw-w-64`} href="/admin">
|
||||
<WrenchIcon />
|
||||
Administration
|
||||
<Link
|
||||
className={`${btnClasses} tw:daisy-btn-accent tw:md:w-64 tw:text-accent-content`}
|
||||
href="/admin"
|
||||
>
|
||||
<WrenchIcon className="tw:w-6 tw:h-6 tw:text-accent-content" />
|
||||
<span className="tw:text-accent-content">Administration</span>
|
||||
</Link>
|
||||
)}
|
||||
{control > 1 && (
|
||||
<Link className={`${btnClasses} tw-daisy-btn-secondary md:tw-w-64`} href="/profile">
|
||||
<UserIcon />
|
||||
Your Profile
|
||||
<Link className={`${btnClasses} tw:daisy-btn-secondary tw:md:w-64`} href="/profile">
|
||||
<UserIcon className="tw:w-6 tw:h-6 tw:text-accent-content" />
|
||||
<span className="tw:text-accent-content">Your Profile</span>
|
||||
</Link>
|
||||
)}
|
||||
<button
|
||||
className={`${btnClasses} tw-daisy-btn-neutral md:tw-w-64`}
|
||||
className={`${btnClasses} tw:daisy-btn-neutral tw:md:w-64`}
|
||||
onClick={() => signOut()}
|
||||
>
|
||||
<SignoutIcon />
|
||||
|
|
|
@ -89,14 +89,14 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
if (enable) titleText = 'Set up Multi-Factor Authentication'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{title ? <h2>{titleText}</h2> : null}
|
||||
{enable ? (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-center tw-px-8 lg:tw-px-36">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-center tw:px-8 tw:lg:px-36">
|
||||
<div dangerouslySetInnerHTML={{ __html: enable.qrcode }} />
|
||||
</div>
|
||||
<p className="tw-flex tw-flex-row tw-items-center tw-justify-center">{enable.secret}</p>
|
||||
<p className="tw:flex tw:flex-row tw:items-center tw:justify-center">{enable.secret}</p>
|
||||
<Bullet num="1">
|
||||
Add FreeSewing to your Authenticator App by scanning the QR code above. If you cannot
|
||||
scan the QR code, you can manually enter the secret below it.
|
||||
|
@ -107,14 +107,14 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
<input
|
||||
value={code}
|
||||
onChange={(evt) => setCode(evt.target.value)}
|
||||
className="tw-daisy-input tw-w-64 tw-m-auto tw-text-4xl tw-daisy-input-bordered tw-daisy-input-lg tw-flex tw-flex-row tw-text-center tw-mb-8 tw-tracking-widest"
|
||||
className="tw:daisy-input tw:w-64 tw:m-auto tw:text-4xl tw:daisy-input-bordered tw:daisy-input-lg tw:flex tw:flex-row tw:text-center tw:mb-8 tw:tracking-widest"
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]{6}"
|
||||
placeholder="000000"
|
||||
/>
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-success tw-daisy-btn-lg tw-block tw-w-full md:tw-w-auto tw-mx-auto`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-success tw:daisy-btn-lg tw:block tw:w-full tw:md:w-auto tw:mx-auto`}
|
||||
onClick={confirmMfa}
|
||||
>
|
||||
<LockIcon />
|
||||
|
@ -123,7 +123,7 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
</>
|
||||
) : null}
|
||||
{disable ? (
|
||||
<div className="tw-my-8 tw-max-w-xl">
|
||||
<div className="tw:my-8 tw:max-w-xl">
|
||||
<Bullet num="1">
|
||||
<h5>Please enter your password to confirm this action</h5>
|
||||
<PasswordInput
|
||||
|
@ -138,13 +138,13 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
<input
|
||||
value={code}
|
||||
onChange={(evt) => setCode(evt.target.value)}
|
||||
className="tw-input tw-w-full tw-text-4xl tw-input-bordered tw-input-lg tw-flex tw-flex-row tw-text-center tw-mb-8 tw-tracking-widest"
|
||||
className="tw:input tw:w-full tw:text-4xl tw:input-bordered tw:input-lg tw:flex tw:flex-row tw:text-center tw:mb-8 tw:tracking-widest"
|
||||
type="text"
|
||||
placeholder={'000000'}
|
||||
/>
|
||||
</Bullet>
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-error tw-daisy-btn-lg`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-error tw:daisy-btn-lg`}
|
||||
onClick={disableMfa}
|
||||
disabled={code.length < 4 || password.length < 3}
|
||||
>
|
||||
|
@ -163,8 +163,8 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
You can use each of these codes only once. Write them down, because this is the only
|
||||
time you will get to see them.
|
||||
</p>
|
||||
<div className="hljs tw-my-4">
|
||||
<div className="tw-flex tw-flex-row tw-justify-between tw-items-center tw-text-xs tw-font-medium tw-text-warning tw-mt-1 tw-border-b tw-border-neutral-content tw-border-opacity-25 tw-px-4 tw-py-1 tw-mb-2 lg:tw-text-sm">
|
||||
<div className="hljs tw:my-4">
|
||||
<div className="tw:flex tw:flex-row tw:justify-between tw:items-center tw:text-xs tw:font-medium tw:text-warning tw:mt-1 tw:border-b tw:border-neutral-content tw:border-opacity-25 tw:px-4 tw:py-1 tw:mb-2 tw:lg:text-sm">
|
||||
<span>MFA Scratch Codes</span>
|
||||
<CopyToClipboardButton
|
||||
content={
|
||||
|
@ -173,17 +173,17 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
<pre className="language-shell hljs tw-text-base lg:tw-text-lg tw-whitespace-break-spaces tw-overflow-scroll tw-pr-4">
|
||||
<pre className="language-shell hljs tw:text-base tw:lg:text-lg tw:whitespace-break-spaces tw:overflow-scroll tw:pr-4">
|
||||
{scratchCodes.map((code) => code + '\n')}
|
||||
</pre>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="tw-mt-4">
|
||||
<div className="tw:mt-4">
|
||||
{account.mfaEnabled ? (
|
||||
disable ? null : (
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-primary tw-w-full md:tw-w-auto tw-daisy-btn-outline`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:md:w-auto tw:daisy-btn-outline`}
|
||||
onClick={() => setDisable(true)}
|
||||
>
|
||||
<NoIcon stroke={3} />
|
||||
|
@ -193,7 +193,7 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
) : enable ? null : (
|
||||
<div>
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-primary tw-w-full md:tw-w-auto tw-daisy-btn-lg`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:md:w-auto tw:daisy-btn-lg`}
|
||||
onClick={enableMfa}
|
||||
>
|
||||
<LockIcon />
|
||||
|
@ -215,10 +215,10 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
}
|
||||
|
||||
const Bullet = ({ num, children }) => (
|
||||
<div className="tw-flex tw-flex-row tw-items-start tw-py-4 tw-w-full tw-gap-4">
|
||||
<span className="tw-bg-secondary tw-text-secondary-content tw-rounded-full tw-w-8 tw-h-8 tw-p-1 tw-inline-block tw-text-center tw-font-bold tw-mr-4 tw-shrink-0">
|
||||
<div className="tw:flex tw:flex-row tw:items-start tw:py-4 tw:w-full tw:gap-4">
|
||||
<span className="tw:bg-secondary tw:text-secondary-content tw:rounded-full tw:w-8 tw:h-8 tw:p-1 tw:inline-block tw:text-center tw:font-bold tw:mr-4 tw:shrink-0">
|
||||
{num}
|
||||
</span>
|
||||
<div className="tw-text-lg tw-grow">{children}</div>
|
||||
<div className="tw:text-lg tw:grow">{children}</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -58,21 +58,21 @@ export const Newsletter = ({ welcome = false, Link = false }) => {
|
|||
: '/docs/about/guide'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<ListInput
|
||||
id="account-newsletter"
|
||||
label="Would you like to receive the FreeSewing newsletter?"
|
||||
list={['yes', 'no'].map((val) => ({
|
||||
val,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-w-full tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:w-full tw:justify-between">
|
||||
<span>
|
||||
{val === 'yes' ? 'Yes, I would like to receive the newsletter' : 'No thanks'}
|
||||
</span>
|
||||
{val === 'yes' ? (
|
||||
<OkIcon className="tw-w-8 tw-h-8 tw-text-success" stroke={4} />
|
||||
<OkIcon className="tw:w-8 tw:h-8 tw:text-success" stroke={4} />
|
||||
) : (
|
||||
<NoIcon className="tw-w-8 tw-h-8 tw-text-error" stroke={3} />
|
||||
<NoIcon className="tw:w-8 tw:h-8 tw:text-error" stroke={3} />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
|
@ -86,17 +86,17 @@ export const Newsletter = ({ welcome = false, Link = false }) => {
|
|||
/>
|
||||
{welcome ? (
|
||||
<>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[account?.control].length > 0 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-daisy-progress tw-daisy-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:daisy-progress tw:daisy-progress-primary tw:w-full tw:mt-12"
|
||||
value={200 / welcomeSteps[account?.control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
2 / {welcomeSteps[account?.control].length}
|
||||
</span>
|
||||
<WelcomeIcons
|
||||
|
@ -120,7 +120,7 @@ export const Newsletter = ({ welcome = false, Link = false }) => {
|
|||
Unsubscribe link
|
||||
</Link>
|
||||
</p>
|
||||
<p className="tw-text-sm">
|
||||
<p className="tw:text-sm">
|
||||
This link is to unsubscribe you specifically, do not share it with other subscribers.
|
||||
</p>
|
||||
</Popout>
|
||||
|
|
|
@ -43,7 +43,7 @@ export const Password = ({ welcome = false, Link = false }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<PasswordInput
|
||||
id="account-password"
|
||||
label="Something only you know"
|
||||
|
@ -53,7 +53,7 @@ export const Password = ({ welcome = false, Link = false }) => {
|
|||
placeholder="Tip: use a password manager"
|
||||
/>
|
||||
<button
|
||||
className={`tw-flex tw-flex-row tw-gap-2 tw-items-center tw-daisy-btn tw-justify-between tw-daisy-btn-primary tw-w-full md:tw-w-auto tw-w-full`}
|
||||
className={`tw:flex tw:flex-row tw:gap-2 tw:items-center tw:daisy-btn tw:justify-between tw:daisy-btn-primary tw:w-full tw:md:w-auto tw:w-full`}
|
||||
onClick={save}
|
||||
disabled={password.length < 4}
|
||||
>
|
||||
|
@ -66,9 +66,9 @@ export const Password = ({ welcome = false, Link = false }) => {
|
|||
We do not enforce a password policy, but we do recommend you enable Two-Factor
|
||||
Authentication to keep your FreeSewing account safe.
|
||||
</p>
|
||||
<p className="tw-text-right tw-m-0 tw-pt-0">
|
||||
<Link className="tw-daisy-btn tw-daisy-btn-accent" href="/account/mfa">
|
||||
Two-Factor Authentication <RightIcon className="tw-h-6 tw-w-6 tw-ml-2" />
|
||||
<p className="tw:text-right tw:m-0 tw:pt-0">
|
||||
<Link className="tw:daisy-btn tw:daisy-btn-accent" href="/account/mfa">
|
||||
Two-Factor Authentication <RightIcon className="tw:h-6 tw:w-6 tw:ml-2" />
|
||||
</Link>
|
||||
</p>
|
||||
</Popout>
|
||||
|
|
|
@ -135,7 +135,7 @@ export const Pattern = ({ id, Link }) => {
|
|||
|
||||
if (!edit)
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{pattern.public ? (
|
||||
<Popout note>
|
||||
<h5>This is the private view of your pattern</h5>
|
||||
|
@ -144,9 +144,9 @@ export const Pattern = ({ id, Link }) => {
|
|||
<br />
|
||||
But only you can access this private view.
|
||||
</p>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<Link
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary hover:tw-text-secondary-content hover:tw-no-underline`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:hover:text-secondary-content tw:hover:no-underline`}
|
||||
href={`/pattern?id=${pattern.id}`}
|
||||
>
|
||||
<PatternIcon />
|
||||
|
@ -166,7 +166,7 @@ export const Pattern = ({ id, Link }) => {
|
|||
)
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<h2>Edit pattern {pattern.name}</h2>
|
||||
|
||||
{/* Name is always shown */}
|
||||
|
@ -204,10 +204,10 @@ export const Pattern = ({ id, Link }) => {
|
|||
{
|
||||
val: true,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-justify-between tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:justify-between tw:w-full">
|
||||
<span>Public Pattern</span>
|
||||
<OkIcon
|
||||
className="tw-w-8 tw-h-8 tw-text-success tw-bg-base-100 tw-rounded-full tw-p-1"
|
||||
className="tw:w-8 tw:h-8 tw:text-success tw:bg-base-100 tw:rounded-full tw:p-1"
|
||||
stroke={4}
|
||||
/>
|
||||
</div>
|
||||
|
@ -217,10 +217,10 @@ export const Pattern = ({ id, Link }) => {
|
|||
{
|
||||
val: false,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-justify-between tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:justify-between tw:w-full">
|
||||
<span>Private Pattern</span>
|
||||
<NoIcon
|
||||
className="tw-w-8 tw-h-8 tw-text-error tw-bg-base-100 tw-rounded-full tw-p-1"
|
||||
className="tw:w-8 tw:h-8 tw:text-error tw:bg-base-100 tw:rounded-full tw:p-1"
|
||||
stroke={3}
|
||||
/>
|
||||
</div>
|
||||
|
@ -237,15 +237,15 @@ export const Pattern = ({ id, Link }) => {
|
|||
{account.control >= controlConfig.account.patterns.notes ? (
|
||||
<MarkdownInput id="pattern-notes" label="Notes" update={setNotes} current={notes} />
|
||||
) : null}
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-align-end tw-gap-2 tw-mt-8">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:align-end tw:gap-2 tw:mt-8">
|
||||
<button
|
||||
onClick={() => setEdit(false)}
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline`}
|
||||
>
|
||||
<ResetIcon />
|
||||
Cancel
|
||||
</button>
|
||||
<button onClick={save} className="tw-daisy-btn tw-daisy-btn-primary tw-grow">
|
||||
<button onClick={save} className="tw:daisy-btn tw:daisy-btn-primary tw:grow">
|
||||
<UploadIcon />
|
||||
Save Pattern
|
||||
</button>
|
||||
|
@ -272,7 +272,7 @@ export const PatternCard = ({
|
|||
const s = sizes[size]
|
||||
|
||||
const wrapperProps = {
|
||||
className: `tw-bg-base-300 tw-w-full tw-mb-2 tw-mx-auto tw-flex tw-flex-col tw-items-start tw-text-center tw-justify-center tw-rounded tw-shadow tw-py-4 tw-w-${s} tw-aspect-square`,
|
||||
className: `tw:bg-base-300 tw:w-full tw:mb-2 tw:mx-auto tw:flex tw:flex-col tw:items-start tw:text-center tw:justify-center tw:rounded tw:shadow tw:py-4 tw:w-${s} tw:aspect-square`,
|
||||
style: {
|
||||
backgroundImage: `url(${cloudflareImageUrl({ type: 'w1000', id: pattern.img })})`,
|
||||
backgroundSize: 'cover',
|
||||
|
@ -315,7 +315,7 @@ export const PatternCard = ({
|
|||
const BadgeLink = ({ label, href }) => (
|
||||
<a
|
||||
href={href}
|
||||
className="tw-daisy-badge tw-daisy-badge-secondary tw-font-bold tw-daisy-badge-lg hover:tw-text-secondary-content hover:tw-no-underline"
|
||||
className="tw:daisy-badge tw:daisy-badge-secondary tw:font-bold tw:daisy-badge-lg tw:hover:text-secondary-content tw:hover:no-underline"
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
|
@ -336,19 +336,19 @@ const PatternHeader = ({
|
|||
}) => (
|
||||
<>
|
||||
<h2>{pattern.name}</h2>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-2 tw-text-sm tw-items-center tw-mb-2">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-2 tw:text-sm tw:items-center tw:mb-2">
|
||||
<KeyVal k="ID" val={pattern.id} color="secondary" />
|
||||
<KeyVal k="Created" val={<TimeAgo iso={pattern.createdAt} />} color="secondary" />
|
||||
<KeyVal k="Updated" val={<TimeAgo iso={pattern.updatedAt} />} color="secondary" />
|
||||
<KeyVal k="Public" val={pattern.public ? 'yes' : 'no'} color="secondary" />
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-wrap md:tw-flex-nowrap tw-flex-row tw-gap-2 tw-w-full">
|
||||
<div className="tw-w-full md:tw-w-96 tw-shrink-0">
|
||||
<div className="tw:flex tw:flex-wrap tw:md:flex-nowrap tw:flex-row tw:gap-2 tw:w-full">
|
||||
<div className="tw:w-full tw:md:w-96 tw:shrink-0">
|
||||
<PatternCard pattern={pattern} size="md" Link={Link} />
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-col tw-justify-end tw-gap-2 tw-mb-2 tw-grow">
|
||||
<div className="tw:flex tw:flex-col tw:justify-end tw:gap-2 tw:mb-2 tw:grow">
|
||||
{account.control > 3 && (pattern?.public || pattern.userId === account.id) ? (
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<BadgeLink label="JSON" href={`${urls.backend}/patterns/${pattern.id}.json`} />
|
||||
<BadgeLink label="YAML" href={`${urls.backend}/patterns/${pattern.id}.yaml`} />
|
||||
</div>
|
||||
|
@ -358,12 +358,12 @@ const PatternHeader = ({
|
|||
<button
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper flex="col" justify="top lg:tw-justify-center" slideFrom="right">
|
||||
<ModalWrapper flex="col" justify="top tw:lg:justify-center" slideFrom="right">
|
||||
<img src={cloudflareImageUrl({ type: 'public', id: pattern.img })} />
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline ${horFlexClasses}`}
|
||||
>
|
||||
<ShowcaseIcon />
|
||||
Show Image
|
||||
|
@ -371,7 +371,7 @@ const PatternHeader = ({
|
|||
{account.control > 3 ? (
|
||||
<button
|
||||
onClick={() => togglePublic()}
|
||||
className={`tw-daisy-btn tw-daisy-btn-${pattern.public ? 'error' : 'success'} tw-daisy-btn-outline ${horFlexClasses} hover:tw-text-${pattern.public ? 'error' : 'success'}-content`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-${pattern.public ? 'error' : 'success'} tw:daisy-btn-outline ${horFlexClasses} hover:tw:text-${pattern.public ? 'error' : 'success'}-content`}
|
||||
>
|
||||
{pattern.public ? <BoolNoIcon /> : <BoolYesIcon />}
|
||||
Make pattern {pattern.public ? 'private' : 'public'}
|
||||
|
@ -381,19 +381,19 @@ const PatternHeader = ({
|
|||
<>
|
||||
<Link
|
||||
href={patternUrlFromState(pattern, true)}
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline ${horFlexClasses}`}
|
||||
>
|
||||
<FreeSewingIcon /> Update Pattern
|
||||
</Link>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline ${horFlexClasses}`}
|
||||
onClick={clone}
|
||||
>
|
||||
<CloneIcon /> Clone Pattern
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setEdit(true)}
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary ${horFlexClasses}`}
|
||||
>
|
||||
<EditIcon /> Edit Pattern Metadata
|
||||
</button>
|
||||
|
|
|
@ -89,16 +89,16 @@ export const Patterns = ({ Link = false }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-2 tw-items-center tw-justify-between tw-mb-4">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-2 tw:items-center tw:justify-between tw:mb-4">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-error"
|
||||
className="tw:daisy-btn tw:daisy-btn-error"
|
||||
onClick={removeSelectedPatterns}
|
||||
disabled={count < 1}
|
||||
>
|
||||
<TrashIcon /> {count} {t('patterns')}
|
||||
</button>
|
||||
<Link
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-capitalize tw-w-full md:tw-w-auto hover:tw-text-primary-content"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize tw:w-full tw:md:w-auto tw:hover:text-primary-content"
|
||||
href="/editor/"
|
||||
>
|
||||
<PlusIcon />
|
||||
|
@ -106,13 +106,13 @@ export const Patterns = ({ Link = false }) => {
|
|||
</Link>
|
||||
</div>
|
||||
<TableWrapper>
|
||||
<table className="tw-table tw-table-auto">
|
||||
<thead className="tw-border tw-border-base-300 tw-border-b-2 tw-border-t-0 tw-border-x-0">
|
||||
<table className="tw:table tw:table-auto">
|
||||
<thead className="tw:border tw:border-base-300 tw:border-b-2 tw:border-t-0 tw:border-x-0">
|
||||
<tr className="">
|
||||
<th className="">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={toggleAll}
|
||||
checked={patterns.length === count}
|
||||
/>
|
||||
|
@ -120,13 +120,13 @@ export const Patterns = ({ Link = false }) => {
|
|||
{Object.keys(fields).map((field) => (
|
||||
<th key={field}>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-link tw-capitalize tw-px-0 tw-underline hover:tw-decoration-4 tw-decoration-2 tw-text-secondary"
|
||||
className="tw:daisy-btn tw:daisy-btn-link tw:capitalize tw:px-0 tw:underline tw:hover:decoration-4 tw:decoration-2 tw:text-secondary"
|
||||
onClick={() => (order === field ? setDesc(!desc) : setOrder(field))}
|
||||
>
|
||||
{fields[field]}{' '}
|
||||
<RightIcon
|
||||
stroke={3}
|
||||
className={`tw-w-4 tw-h-4 ${desc ? 'tw--' : 'tw-'}rotate-90 ${order === field ? '' : 'tw-opacity-0'}`}
|
||||
className={`tw:w-4 tw:h-4 ${desc ? 'tw:-' : 'tw:'}rotate-90 ${order === field ? '' : 'tw:opacity-0'}`}
|
||||
/>
|
||||
</button>
|
||||
</th>
|
||||
|
@ -136,16 +136,16 @@ export const Patterns = ({ Link = false }) => {
|
|||
<tbody>
|
||||
{orderBy(patterns, order, desc ? 'desc' : 'asc').map((pattern, i) => (
|
||||
<tr key={i}>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selection[pattern.id] ? true : false}
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={() => toggle(pattern.id)}
|
||||
/>
|
||||
</td>
|
||||
<td className="tw-text-base tw-font-medium">{pattern.id}</td>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">{pattern.id}</td>
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<PatternCard
|
||||
href={`/account/data/patterns/pattern?id=${pattern.id}`}
|
||||
pattern={pattern}
|
||||
|
@ -153,24 +153,24 @@ export const Patterns = ({ Link = false }) => {
|
|||
Link={Link}
|
||||
/>
|
||||
</td>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<Link
|
||||
href={`/account/data/patterns/pattern?id=${pattern.id}`}
|
||||
className="tw-text-secondary tw-underline tw-decoration-2 hover:tw-decoration-4"
|
||||
className="tw:text-secondary tw:underline tw:decoration-2 tw:hover:decoration-4"
|
||||
>
|
||||
{pattern.name}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
<Link
|
||||
href={`/designs/${pattern.design}`}
|
||||
className="tw-text-secondary tw-underline tw-decoration-2 hover:tw-decoration-4"
|
||||
className="tw:text-secondary tw:underline tw:decoration-2 tw:hover:decoration-4"
|
||||
>
|
||||
{capitalize(pattern.design)}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="tw-text-base tw-font-medium">{shortDate(pattern.createdAt)}</td>
|
||||
<td className="tw-text-base tw-font-medium">
|
||||
<td className="tw:text-base tw:font-medium">{shortDate(pattern.createdAt)}</td>
|
||||
<td className="tw:text-base tw:font-medium">
|
||||
{pattern.public ? <BoolYesIcon /> : <BoolNoIcon />}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -56,7 +56,7 @@ const Platform = ({ platform = false }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<StringInput
|
||||
id={`account-${platform}`}
|
||||
label={platform === 'website' ? `Website URL` : `${labels[platform]} account`}
|
||||
|
@ -65,9 +65,9 @@ const Platform = ({ platform = false }) => {
|
|||
valid={(val) => val.length > 0}
|
||||
placeholder={'joostdecock'}
|
||||
/>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto tw:mt-8"
|
||||
onClick={save}
|
||||
>
|
||||
<SaveIcon /> Save
|
||||
|
|
|
@ -32,7 +32,7 @@ export const Reload = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<p>
|
||||
The data stored in your browser can sometimes get out of sync with the data stored in our
|
||||
backend.
|
||||
|
|
|
@ -48,22 +48,22 @@ export const Remove = () => {
|
|||
)
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper keepOpenOnClick>
|
||||
<div className="tw-text-center tw-w-full">
|
||||
<div className="tw:text-center tw:w-full">
|
||||
<h2>There is no way back from this</h2>
|
||||
<p>If this is what you want, then go ahead.</p>
|
||||
<IconButton onClick={removeAccount} color="error" className="tw-mx-auto">
|
||||
<IconButton onClick={removeAccount} color="error" className="tw:mx-auto">
|
||||
<TrashIcon />
|
||||
Remove your FreeSewing account
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={clearModal}
|
||||
color="primary"
|
||||
className="tw-mx-auto tw-daisy-btn-outline tw-mt-4"
|
||||
className="tw:mx-auto tw:daisy-btn-outline tw:mt-4"
|
||||
>
|
||||
<ExitIcon />
|
||||
Back to safety
|
||||
|
|
|
@ -53,7 +53,7 @@ export const Restrict = ({ Link = false }) => {
|
|||
)
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<p>
|
||||
The GDPR guarantees{' '}
|
||||
<Link href="/docs/about/rights/#the-right-to-restrict-processing" className={linkClasses}>
|
||||
|
@ -66,21 +66,21 @@ export const Restrict = ({ Link = false }) => {
|
|||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper keepOpenOnClick>
|
||||
<div className="tw-text-center tw-w-full tw-max-w-xl">
|
||||
<div className="tw:text-center tw:w-full tw:max-w-xl">
|
||||
<h2>Proceed with caution</h2>
|
||||
<p>
|
||||
While no data will be removed, this will disable your account. Furthermore, you
|
||||
can not undo this on your own, but will have to contact support when you want to
|
||||
restore access to your account.
|
||||
</p>
|
||||
<IconButton onClick={restrictAccount} color="error" className="tw-mx-auto">
|
||||
<IconButton onClick={restrictAccount} color="error" className="tw:mx-auto">
|
||||
<NoIcon stroke={3} />
|
||||
Restrict processing of your FreeSewing data
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={clearModal}
|
||||
color="primary"
|
||||
className="tw-mx-auto tw-daisy-btn-outline tw-mt-4"
|
||||
className="tw:mx-auto tw:daisy-btn-outline tw:mt-4"
|
||||
>
|
||||
<BackIcon />
|
||||
Back to safety
|
||||
|
|
|
@ -208,21 +208,21 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
|
||||
const heading = (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-wrap md:tw-flex-nowrap tw-flex-row tw-gap-2 tw-w-full">
|
||||
<div className="tw-w-full md:tw-w-96 tw-shrink-0">
|
||||
<div className="tw:flex tw:flex-wrap tw:md:flex-nowrap tw:flex-row tw:gap-2 tw:w-full">
|
||||
<div className="tw:w-full tw:md:w-96 tw:shrink-0">
|
||||
<MsetCard set={mset} control={control} Link={Link} />
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-col tw-justify-end tw-gap-2 tw-mb-2 tw-grow">
|
||||
<div className="tw:flex tw:flex-col tw:justify-end tw:gap-2 tw:mb-2 tw:grow">
|
||||
{account.control > 2 && mset.public && mset.userId !== account.id ? (
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<a
|
||||
className="tw-daisy-badge tw-daisy-badge-secondary tw-font-bold tw-daisy-badge-lg"
|
||||
className="tw:daisy-badge tw:daisy-badge-secondary tw:font-bold tw:daisy-badge-lg"
|
||||
href={`${urls.backend}/sets/${mset.id}.json`}
|
||||
>
|
||||
JSON
|
||||
</a>
|
||||
<a
|
||||
className="tw-daisy-badge tw-daisy-badge-success tw-font-bold tw-daisy-badge-lg"
|
||||
className="tw:daisy-badge tw:daisy-badge-success tw:font-bold tw:daisy-badge-lg"
|
||||
href={`${urls.backend}/sets/${mset.id}.yaml`}
|
||||
>
|
||||
YAML
|
||||
|
@ -232,9 +232,9 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
<span></span>
|
||||
)}
|
||||
{account.control > 3 && mset.userId === account.id ? (
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<button
|
||||
className="tw-daisy-badge tw-daisy-badge-secondary tw-font-bold tw-daisy-badge-lg"
|
||||
className="tw:daisy-badge tw:daisy-badge-secondary tw:font-bold tw:daisy-badge-lg"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper keepOpenOnClick>
|
||||
|
@ -246,7 +246,7 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
JSON
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-badge tw-daisy-badge-success tw-font-bold tw-daisy-badge-lg tw-text-neutral-content"
|
||||
className="tw:daisy-badge tw:daisy-badge-success tw:font-bold tw:daisy-badge-lg tw:text-neutral-content"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper keepOpenOnClick>
|
||||
|
@ -263,11 +263,11 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
)}
|
||||
{account.id && account.control > 2 && mset.public && mset.userId !== account.id ? (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary"
|
||||
title="Import measurements set"
|
||||
onClick={importSet}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-justify-between tw-items-center tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:justify-between tw:items-center tw:w-full">
|
||||
<UploadIcon />
|
||||
Import measurements set
|
||||
</div>
|
||||
|
@ -284,7 +284,7 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary tw-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:btn-outline ${horFlexClasses}`}
|
||||
>
|
||||
<ShowcaseIcon />
|
||||
Show Image
|
||||
|
@ -297,9 +297,9 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
setSuggest(!suggest)
|
||||
setEdit(false)
|
||||
}}
|
||||
className={`tw-daisy-btn ${
|
||||
suggest ? 'tw-daisy-btn-neutral' : 'tw-daisy-btn-primary'
|
||||
} tw-daisy-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn ${
|
||||
suggest ? 'tw:daisy-btn-neutral' : 'tw:daisy-btn-primary'
|
||||
} tw:daisy-btn-outline ${horFlexClasses}`}
|
||||
>
|
||||
{suggest ? <ResetIcon /> : <CuratedMeasurementsSetIcon />}
|
||||
{suggest ? 'Cancel' : 'Suggest for curation'}
|
||||
|
@ -312,14 +312,14 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
setEdit(false)
|
||||
setSuggest(false)
|
||||
}}
|
||||
className={`tw-daisy-btn tw-daisy-btn-neutral tw-daisy-btn-outline ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-neutral tw:daisy-btn-outline ${horFlexClasses}`}
|
||||
>
|
||||
<ResetIcon />
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={save}
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary ${horFlexClasses}`}
|
||||
>
|
||||
<UploadIcon />
|
||||
Save measurements set
|
||||
|
@ -331,7 +331,7 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
setEdit(true)
|
||||
setSuggest(false)
|
||||
}}
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary ${horFlexClasses}`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary ${horFlexClasses}`}
|
||||
>
|
||||
<EditIcon /> Edit measurements set
|
||||
</button>
|
||||
|
@ -340,14 +340,14 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
)}
|
||||
{account.control > 1 && account?.compare ? (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:btn-outline"
|
||||
title="Validate measurements"
|
||||
onClick={() => {
|
||||
setRender(!render)
|
||||
setEdit(false)
|
||||
}}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-justify-between tw-items-center tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:justify-between tw:items-center tw:w-full">
|
||||
<CompareIcon />
|
||||
Validate measurements
|
||||
</div>
|
||||
|
@ -355,11 +355,11 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
) : null}
|
||||
{account.control > 2 && mset.userId === account.id ? (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-neutral"
|
||||
className="tw:daisy-btn tw:daisy-btn-neutral"
|
||||
title="Clone measurements set"
|
||||
onClick={importSet}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-justify-between tw-items-center tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:justify-between tw:items-center tw:w-full">
|
||||
<CloneIcon />
|
||||
Clone measurements set
|
||||
</div>
|
||||
|
@ -367,13 +367,13 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-4 tw-text-sm tw-items-center tw-justify-between tw-mb-2"></div>
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-4 tw:text-sm tw:items-center tw:justify-between tw:mb-2"></div>
|
||||
</>
|
||||
)
|
||||
|
||||
if (suggest)
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{heading}
|
||||
<SuggestCset {...{ mset, setLoadingStatus, backend, Link }} />
|
||||
</div>
|
||||
|
@ -382,14 +382,14 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
if (!edit) {
|
||||
if (render)
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{heading}
|
||||
<RenderedCSet {...{ mset, setLoadingStatus, backend, imperial }} />
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{heading}
|
||||
|
||||
<h2>Data</h2>
|
||||
|
@ -404,14 +404,14 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
<>
|
||||
{mset.userId === account.id && (
|
||||
<DisplayRow title="Public">
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:justify-between">
|
||||
{mset.public ? (
|
||||
<OkIcon className="tw-w-6 tw-h-6 tw-text-success" stroke={4} />
|
||||
<OkIcon className="tw:w-6 tw:h-6 tw:text-success" stroke={4} />
|
||||
) : (
|
||||
<NoIcon className="tw-w-6 tw-h-6 tw-text-error" stroke={3} />
|
||||
<NoIcon className="tw:w-6 tw:h-6 tw:text-error" stroke={3} />
|
||||
)}
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-sm"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-sm"
|
||||
onClick={togglePublic}
|
||||
>
|
||||
Make {mset.public ? 'Private' : 'Public'}
|
||||
|
@ -432,13 +432,13 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
{control >= controlConfig.account.sets.createdAt && (
|
||||
<DisplayRow title="Created">
|
||||
{timeAgo(mset.createdAt, false)}
|
||||
<span className="tw-text-sm tw-pl-2">({shortDate(mset.createdAt, false)})</span>
|
||||
<span className="tw:text-sm tw:pl-2">({shortDate(mset.createdAt, false)})</span>
|
||||
</DisplayRow>
|
||||
)}
|
||||
{control >= controlConfig.account.sets.updatedAt && (
|
||||
<DisplayRow title="Updated">
|
||||
{timeAgo(mset.updatedAt, false)}
|
||||
<span className="tw-text-sm tw-pl-2">({shortDate(mset.updatedAt, false)})</span>
|
||||
<span className="tw:text-sm tw:pl-2">({shortDate(mset.updatedAt, false)})</span>
|
||||
</DisplayRow>
|
||||
)}
|
||||
{control >= controlConfig.account.sets.id && <DisplayRow title="ID">{mset.id}</DisplayRow>}
|
||||
|
@ -458,7 +458,7 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
title={<MeasurementValue {...{ m, val, imperial: !displayAsMetric }} />}
|
||||
key={m}
|
||||
>
|
||||
<span className="tw-font-medium">{measurementTranslations[m]}</span>
|
||||
<span className="tw:font-medium">{measurementTranslations[m]}</span>
|
||||
</DisplayRow>
|
||||
) : null
|
||||
)}
|
||||
|
@ -469,10 +469,10 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
{heading}
|
||||
<h2 id="measies">Measurements</h2>
|
||||
<div className="tw-bg-secondary tw-px-4 tw-pt-1 tw-pb-4 tw-rounded-lg tw-shadow tw-bg-opacity-10">
|
||||
<div className="tw:bg-secondary/10 tw:px-4 tw:pt-1 tw:pb-4 tw:rounded-lg tw:shadow">
|
||||
<DesignInput
|
||||
update={setFilter}
|
||||
label="Filter by design"
|
||||
|
@ -531,10 +531,10 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
{
|
||||
val: true,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-justify-between tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:justify-between tw:w-full">
|
||||
<span>Public measurements set</span>
|
||||
<OkIcon
|
||||
className="tw-w-8 tw-h-8 tw-text-success tw-bg-base-100 tw-rounded-full tw-p-1"
|
||||
className="tw:w-8 tw:h-8 tw:text-success tw:bg-base-100 tw:rounded-full tw:p-1"
|
||||
stroke={4}
|
||||
/>
|
||||
</div>
|
||||
|
@ -544,10 +544,10 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
{
|
||||
val: false,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-justify-between tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:justify-between tw:w-full">
|
||||
<span>Private measurements set</span>
|
||||
<NoIcon
|
||||
className="tw-w-8 tw-h-8 tw-text-error tw-bg-base-100 tw-rounded-full tw-p-1"
|
||||
className="tw:w-8 tw:h-8 tw:text-error tw:bg-base-100 tw:rounded-full tw:p-1"
|
||||
stroke={3}
|
||||
/>
|
||||
</div>
|
||||
|
@ -571,9 +571,9 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
{
|
||||
val: false,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-justify-between tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:justify-between tw:w-full">
|
||||
<span>Metric units (cm)</span>
|
||||
<span className="tw-text-inherit tw-text-2xl tw-pr-2">cm</span>
|
||||
<span className="tw:text-inherit tw:text-2xl tw:pr-2">cm</span>
|
||||
</div>
|
||||
),
|
||||
desc: 'Pick this if you prefer cm over inches',
|
||||
|
@ -581,9 +581,9 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
{
|
||||
val: true,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-justify-between tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:justify-between tw:w-full">
|
||||
<span>Imperial units (inch)</span>
|
||||
<span className="tw-text-inherit tw-text-4xl tw-pr-2">″</span>
|
||||
<span className="tw:text-inherit tw:text-4xl tw:pr-2">″</span>
|
||||
</div>
|
||||
),
|
||||
desc: 'Pick this if you prefer inches over cm',
|
||||
|
@ -591,7 +591,7 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
]}
|
||||
current={imperial}
|
||||
/>
|
||||
<span className="tw-text-large tw-text-warning">
|
||||
<span className="tw:text-large tw:text-warning">
|
||||
Note: You must save after changing Units to have the change take effect on this page.
|
||||
</span>
|
||||
</>
|
||||
|
@ -610,7 +610,7 @@ export const Set = ({ id, publicOnly = false, Link = false, measurementHelpProvi
|
|||
) : null}
|
||||
<button
|
||||
onClick={save}
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-lg tw-flex tw-flex-row tw-items-center tw-gap-4 tw-mx-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-lg tw:flex tw:flex-row tw:items-center tw:gap-4 tw:mx-auto tw:mt-8"
|
||||
>
|
||||
<UploadIcon />
|
||||
Save Measurements Set
|
||||
|
@ -685,7 +685,7 @@ export const SuggestCset = ({ mset, Link }) => {
|
|||
return (
|
||||
<>
|
||||
<h2>Suggest a measurements set for curation</h2>
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
{missing.length > 0 ? <BoolNoIcon /> : <BoolYesIcon />}
|
||||
Measurements
|
||||
</h4>
|
||||
|
@ -696,7 +696,7 @@ export const SuggestCset = ({ mset, Link }) => {
|
|||
of measurements.
|
||||
</p>
|
||||
<p>Your measurements set is missing the following measurements:</p>
|
||||
<ul className="tw-list tw-list-inside tw-list-disc tw-ml-4">
|
||||
<ul className="tw:list tw:list-inside tw:list-disc tw:ml-4">
|
||||
{missing.map((m) => (
|
||||
<li key={m}>{m}</li>
|
||||
))}
|
||||
|
@ -705,13 +705,13 @@ export const SuggestCset = ({ mset, Link }) => {
|
|||
) : (
|
||||
<p>All measurements are available.</p>
|
||||
)}
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
{name.length > 1 ? <BoolYesIcon /> : <BoolNoIcon />}
|
||||
Name
|
||||
</h4>
|
||||
<p>Each curated set has a name. You can suggest your own name or a pseudonym.</p>
|
||||
<StringInput label="Name" current={name} update={setName} valid={(val) => val.length > 1} />
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
{height.length > 1 ? <BoolYesIcon /> : <BoolNoIcon />}
|
||||
Height
|
||||
</h4>
|
||||
|
@ -725,7 +725,7 @@ export const SuggestCset = ({ mset, Link }) => {
|
|||
update={setHeight}
|
||||
valid={(val) => val.length > 1}
|
||||
/>
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2 tw-mt-4">
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2 tw:mt-4">
|
||||
{img.length > 0 ? <BoolYesIcon /> : <BoolNoIcon />}
|
||||
Image
|
||||
</h4>
|
||||
|
@ -740,7 +740,7 @@ export const SuggestCset = ({ mset, Link }) => {
|
|||
update={setImg}
|
||||
valid={(val) => val.length > 1}
|
||||
/>
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2 tw-mt-4">
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2 tw:mt-4">
|
||||
<BoolYesIcon />
|
||||
Notes
|
||||
</h4>
|
||||
|
@ -750,7 +750,7 @@ export const SuggestCset = ({ mset, Link }) => {
|
|||
</Popout>
|
||||
<MarkdownInput label="Notes" current={notes} update={setNotes} valid={() => true} />
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full tw-mt-4"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:mt-4"
|
||||
disabled={!(missing.length === 0 && height.length > 1 && img.length > 0)}
|
||||
onClick={suggestSet}
|
||||
>
|
||||
|
@ -776,10 +776,10 @@ export const RenderedCSet = ({ mset, imperial }) => {
|
|||
if (missing.length > 0)
|
||||
return (
|
||||
<>
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2">Validation messages</h4>
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2">Validation messages</h4>
|
||||
<p>To validate and preview a measurement set, all measurements need to be entered.</p>
|
||||
<p>Your measurements set is missing the following measurements:</p>
|
||||
<ul className="tw-list tw-list-inside tw-list-disc tw-ml-4">
|
||||
<ul className="tw:list tw:list-inside tw:list-disc tw:ml-4">
|
||||
{missing.map((m) => (
|
||||
<li key={m}>{m}</li>
|
||||
))}
|
||||
|
@ -793,7 +793,7 @@ export const RenderedCSet = ({ mset, imperial }) => {
|
|||
console.log('flags', pattern, flags, strings)
|
||||
return (
|
||||
<>
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2">Measurement analysis</h4>
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2">Measurement analysis</h4>
|
||||
<p>
|
||||
Based on your measurements, we estimate your body to be about{' '}
|
||||
<strong>{formatMm(pattern.parts[0].front.points.head.y * -1, imperial)}</strong> high.
|
||||
|
@ -803,7 +803,7 @@ export const RenderedCSet = ({ mset, imperial }) => {
|
|||
const desc = strings[flag.desc] || flag.desc
|
||||
|
||||
return (
|
||||
<div key={key} className="tw-flex tw-flex-row tw-mt-4">
|
||||
<div key={key} className="tw:flex tw:flex-row tw:mt-4">
|
||||
{flag.type === 'warn' ? (
|
||||
<MiniNote>
|
||||
<Markdown>{desc}</Markdown>
|
||||
|
@ -817,7 +817,7 @@ export const RenderedCSet = ({ mset, imperial }) => {
|
|||
)
|
||||
})}
|
||||
|
||||
<h4 className="tw-flex tw-flex-row tw-items-center tw-gap-2 tw-mt-12">Preview</h4>
|
||||
<h4 className="tw:flex tw:flex-row tw:items-center tw:gap-2 tw:mt-12">Preview</h4>
|
||||
{previewVisible ? (
|
||||
<Pattern
|
||||
renderProps={pattern.getRenderProps()}
|
||||
|
@ -856,7 +856,7 @@ export const RenderedCSet = ({ mset, imperial }) => {
|
|||
</li>
|
||||
</ul>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary tw-mt-4`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary tw:mt-4`}
|
||||
onClick={() => setPreviewVisible(true)}
|
||||
>
|
||||
<CompareIcon />I understand, render body preview
|
||||
|
@ -896,7 +896,7 @@ export const NewSet = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-max-w-xl">
|
||||
<div className="tw:max-w-xl">
|
||||
<h5>Name</h5>
|
||||
<p>Give this set of measurements a name. That will help tell them apart.</p>
|
||||
<StringInput
|
||||
|
@ -907,9 +907,9 @@ export const NewSet = () => {
|
|||
valid={(val) => val && val.length > 0}
|
||||
placeholder={'Georg Cantor'}
|
||||
/>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-w-full tw-mt-8 tw-mb-2">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:w-full tw:mt-8 tw:mb-2">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-grow tw-capitalize"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:grow tw:capitalize"
|
||||
disabled={name.length < 1}
|
||||
onClick={createSet}
|
||||
>
|
||||
|
|
|
@ -85,19 +85,19 @@ export const Sets = ({ Link = false }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-max-w-7xl xl:tw-pl-4">
|
||||
<p className="tw-text-center md:tw-text-right">
|
||||
<div className="tw:max-w-7xl tw:xl:pl-4">
|
||||
<p className="tw:text-center tw:md:text-right">
|
||||
<Link
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline tw-capitalize tw-w-full md:tw-w-auto tw-mr-2 tw-mb-2 hover:tw-no-underline hover:tw-text-primary-content"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:capitalize tw:w-full tw:md:w-auto tw:mr-2 tw:hover:no-underline tw:hover:text-primary-content no-hover-decoration"
|
||||
bottom
|
||||
primary
|
||||
href="/account/import"
|
||||
>
|
||||
<UploadIcon />
|
||||
Import Measurements Sets
|
||||
<UploadIcon className="tw:w-6 tw:h-6 tw:text-secondary-content" />
|
||||
<span className="tw:text-secondary-content">Import Measurements Sets</span>
|
||||
</Link>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-capitalize tw-w-full md:tw-w-auto hover:tw-no-underline hover:tw-text-primary-content"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize tw:w-full tw:md:w-auto tw:hover:no-underline tw:hover:text-primary-content"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper keepOpenOnClick>
|
||||
|
@ -110,41 +110,41 @@ export const Sets = ({ Link = false }) => {
|
|||
Create a new Measurements Set
|
||||
</button>
|
||||
</p>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-border-b-2 tw-mb-4 tw-pb-4 tw-mt-8 tw-h-14 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:border-b-2 tw:mb-4 tw:pb-4 tw:mt-8 tw:h-14 tw:items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={toggleSelectAll}
|
||||
checked={sets.length === selCount}
|
||||
/>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-error"
|
||||
className="tw:daisy-btn tw:daisy-btn-error"
|
||||
onClick={removeSelectedSets}
|
||||
disabled={selCount < 1}
|
||||
>
|
||||
<TrashIcon /> {selCount} Measurements Sets
|
||||
</button>
|
||||
</div>
|
||||
<div className="tw-grid tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-2">
|
||||
<div className="tw:grid tw:grid-cols-2 tw:lg:grid-cols-4 tw:gap-2">
|
||||
{sets.map((set, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`tw-flex tw-flex-row tw-items-start tw-gap-1 tw-border-2
|
||||
className={`tw:flex tw:flex-row tw:items-start tw:gap-1 tw:border-2
|
||||
${
|
||||
selected[set.id]
|
||||
? 'tw-border-solid tw-border-secondary'
|
||||
: 'tw-border-dotted tw-border-base-300'
|
||||
} tw-rounded-lg p-2`}
|
||||
? 'tw:border-solid tw:border-secondary'
|
||||
: 'tw:border-dotted tw:border-base-300'
|
||||
} tw:rounded-lg p-2`}
|
||||
>
|
||||
<label className="tw-w-8 tw-h-full tw-shrink-0">
|
||||
<label className="tw:w-8 tw:h-full tw:shrink-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selected[set.id] ? true : false}
|
||||
className="tw-daisy-checkbox tw-daisy-checkbox-secondary"
|
||||
className="tw:daisy-checkbox tw:daisy-checkbox-secondary"
|
||||
onClick={() => toggleSelect(set.id)}
|
||||
/>
|
||||
</label>
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<MsetCard
|
||||
control={control}
|
||||
href={`/account/data/sets/set?id=${set.id}`}
|
||||
|
@ -189,9 +189,9 @@ export const MsetCard = ({
|
|||
const s = sizes[size]
|
||||
|
||||
const wrapperProps = {
|
||||
className: `tw-bg-base-300 tw-aspect-square tw-h-${s} tw-w-${s} tw-mb-2 tw-grow tw-w-full
|
||||
hover:tw-cursor-pointer tw-border-0 tw-opacity-80 hover:tw-opacity-100
|
||||
tw-mx-auto tw-flex tw-flex-col tw-items-start tw-text-center tw-justify-between tw-rounded-none md:tw-rounded shadow`,
|
||||
className: `tw:bg-base-300 tw:aspect-square tw:h-${s} tw:w-${s} tw:mb-2 tw:grow tw:w-full
|
||||
tw:hover:cursor-pointer tw:border-0 tw:opacity-80 tw:hover:opacity-100
|
||||
tw:mx-auto tw:flex tw:flex-col tw:items-start tw:text-center tw:justify-between tw:rounded-none tw:md:rounded shadow`,
|
||||
style: {
|
||||
backgroundImage: `url(${cloudflareImageUrl({ type: 'w500', id: set.img })})`,
|
||||
backgroundSize: 'cover',
|
||||
|
@ -212,11 +212,11 @@ export const MsetCard = ({
|
|||
set.measies,
|
||||
true
|
||||
)
|
||||
const iconClasses = 'tw-w-8 tw-h-8 tw-p-1 tw-rounded-full tw--mt-2 tw--ml-2 tw-shadow'
|
||||
const iconClasses = 'tw:w-8 tw:h-8 tw:p-1 tw:rounded-full tw:-mt-2 tw:-ml-2 tw:shadow'
|
||||
icon = hasMeasies ? (
|
||||
<OkIcon className={`${iconClasses} tw-bg-success tw-text-success-content`} stroke={4} />
|
||||
<OkIcon className={`${iconClasses} tw:bg-success tw:text-success-content`} stroke={4} />
|
||||
) : (
|
||||
<NoIcon className={`${iconClasses} tw-bg-error tw-text-error-content`} stroke={3} />
|
||||
<NoIcon className={`${iconClasses} tw:bg-error tw:text-error-content`} stroke={3} />
|
||||
)
|
||||
if (missing.length > 0) {
|
||||
const translated = missing.map((m) => measurementsTranslations[m])
|
||||
|
@ -225,7 +225,7 @@ export const MsetCard = ({
|
|||
const lastSpace = missingString.lastIndexOf(', ', maxLength)
|
||||
missingString = missingString.substring(0, lastSpace) + ', and more...'
|
||||
}
|
||||
const measieClasses = 'tw-font-normal tw-text-xs'
|
||||
const measieClasses = 'tw:font-normal tw:text-xs'
|
||||
missingMeasies = <span className={`${measieClasses}`}>{missingString}</span>
|
||||
linebreak = <br />
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ export const MsetCard = ({
|
|||
const inner = (
|
||||
<>
|
||||
{icon}
|
||||
<span className="tw-bg-neutral tw-text-neutral-content tw-px-4 tw-w-full tw-bg-opacity-50 tw-py-2 tw-rounded tw-rounded-t-none tw-font-bold tw-leading-5">
|
||||
<span className="tw:bg-neutral/50 tw:text-neutral-content tw:px-4 tw:w-full tw:py-2 tw:rounded tw:rounded-t-none tw:font-bold tw:leading-5">
|
||||
{set.name}
|
||||
{linebreak}
|
||||
{missingMeasies}
|
||||
|
|
|
@ -54,14 +54,14 @@ export const Units = ({ welcome = false }) => {
|
|||
: '/docs/about/guide'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<ListInput
|
||||
id="account-units"
|
||||
label="Units"
|
||||
list={['metric', 'imperial'].map((val) => ({
|
||||
val,
|
||||
label: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-w-full tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:w-full tw:justify-between">
|
||||
<span>{val === 'metric' ? 'Metric units (cm)' : 'Imperial units (inch)'}</span>
|
||||
<NumberCircle nr={val === 'imperial' ? '″' : 'cm'} color="secondary" />
|
||||
</div>
|
||||
|
@ -76,17 +76,17 @@ export const Units = ({ welcome = false }) => {
|
|||
/>
|
||||
{welcome ? (
|
||||
<>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[account?.control].length > 0 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-daisy-progress tw-daisy-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:daisy-progress tw:daisy-progress-primary tw:w-full tw:mt-12"
|
||||
value={300 / welcomeSteps[account?.control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
3 / {welcomeSteps[account?.control].length}
|
||||
</span>
|
||||
<WelcomeIcons
|
||||
|
|
|
@ -60,7 +60,7 @@ export const Username = ({ welcome = false, Link = false }) => {
|
|||
else btnClasses += 'w-full daisy-btn-primary'
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw:w-full">
|
||||
<StringInput
|
||||
id="account-username"
|
||||
label="Username"
|
||||
|
@ -69,24 +69,24 @@ export const Username = ({ welcome = false, Link = false }) => {
|
|||
valid={() => available}
|
||||
placeholder={'Sorcha Ni Dhubghaill'}
|
||||
labelBL={
|
||||
<span className="tw-flex tw-flex-row tw-gap-1 tw-items-center">
|
||||
<span className="tw:flex tw:flex-row tw:gap-1 tw:items-center">
|
||||
{available ? (
|
||||
<>
|
||||
<OkIcon className="tw-w-4 tw-h-4 tw-text-success" stroke={4} /> Username is
|
||||
<OkIcon className="tw:w-4 tw:h-4 tw:text-success" stroke={4} /> Username is
|
||||
available
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<NoIcon className="tw-w-4 tw-h-4 tw-text-error" stroke={3} /> This username is taken
|
||||
<NoIcon className="tw:w-4 tw:h-4 tw:text-error" stroke={3} /> This username is taken
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<p className="tw-text-right">
|
||||
<p className="tw:text-right">
|
||||
<button
|
||||
disabled={!available}
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full lg:tw-w-auto tw-mt-8"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full tw:lg:w-auto tw:mt-8"
|
||||
onClick={save}
|
||||
>
|
||||
<SaveIcon /> Save Username
|
||||
|
@ -95,17 +95,17 @@ export const Username = ({ welcome = false, Link = false }) => {
|
|||
|
||||
{welcome ? (
|
||||
<>
|
||||
<IconButton href={nextHref} className="tw-mt-4">
|
||||
<IconButton href={nextHref} className="tw:mt-4">
|
||||
<RightIcon stroke={3} /> Continue
|
||||
</IconButton>
|
||||
{welcomeSteps[account.control].length > 0 ? (
|
||||
<>
|
||||
<progress
|
||||
className="tw-daisy-progress tw-daisy-progress-primary tw-w-full tw-mt-12"
|
||||
className="tw:daisy-progress tw:daisy-progress-primary tw:w-full tw:mt-12"
|
||||
value={500 / welcomeSteps[account.control].length}
|
||||
max="100"
|
||||
></progress>
|
||||
<span className="tw-pt-4 tw-text-sm tw-font-bold tw-opacity-50">
|
||||
<span className="tw:pt-4 tw:text-sm tw:font-bold tw:opacity-50">
|
||||
5 / {welcomeSteps[account.control].length}
|
||||
</span>
|
||||
<WelcomeIcons
|
||||
|
|
|
@ -17,14 +17,14 @@ import {
|
|||
/*
|
||||
* A component to display a row of data
|
||||
*/
|
||||
export const DisplayRow = ({ title, children, keyWidth = 'tw-w-24' }) => (
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-items-center lg:tw-gap-4 tw-my-2 tw-w-full">
|
||||
export const DisplayRow = ({ title, children, keyWidth = 'tw:w-24' }) => (
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:items-center tw:lg:gap-4 tw:my-2 tw:w-full">
|
||||
<div
|
||||
className={`${keyWidth} tw-text-left md:tw-text-right tw-block md:tw-inline tw-font-bold tw-pr-4 tw-shrink-0`}
|
||||
className={`${keyWidth} tw:text-left tw:md:text-right tw:block tw:md:inline tw:font-bold tw:pr-4 tw:shrink-0`}
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
<div className="tw-grow">{children}</div>
|
||||
<div className="tw:grow">{children}</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
|
@ -37,14 +37,14 @@ export const welcomeSteps = {
|
|||
}
|
||||
|
||||
export const WelcomeDoneIcon = ({ href }) => (
|
||||
<Link href={`/welcome/${href}`} className="tw-text-success hover:tw-text-secondary">
|
||||
<Link href={`/welcome/${href}`} className="tw:text-success tw:hover:text-secondary">
|
||||
<WelcomeTopicIcon href={href} />
|
||||
</Link>
|
||||
)
|
||||
export const WelcomeTodoIcon = ({ href }) => (
|
||||
<Link
|
||||
href={`/welcome/${href}`}
|
||||
className="tw-text-secondary tw-w-6 tw-h-6 tw-opacity-50 hover:tw-opacity-100"
|
||||
className="tw:text-secondary tw:w-6 tw:h-6 tw:opacity-50 tw:hover:opacity-100"
|
||||
>
|
||||
<WelcomeTopicIcon href={href} />
|
||||
</Link>
|
||||
|
@ -62,11 +62,11 @@ const WelcomeTopicIcon = (props) => {
|
|||
}
|
||||
|
||||
const WelcomeDoingIcon = ({ href }) => (
|
||||
<WelcomeTopicIcon href={href} className="tw-w-6 tw-h-6 tw-text-base-content" />
|
||||
<WelcomeTopicIcon href={href} className="tw:w-6 tw:h-6 tw:text-base-content" />
|
||||
)
|
||||
|
||||
export const WelcomeIcons = ({ done = [], todo = [], current = '' }) => (
|
||||
<div className="tw-m-auto tw-flex tw-flex-row tw-items-center tw-justify-center tw-gap-2">
|
||||
<div className="tw:m-auto tw:flex tw:flex-row tw:items-center tw:justify-center tw:gap-2">
|
||||
{done.map((href) => (
|
||||
<WelcomeDoneIcon href={href} key={href} />
|
||||
))}
|
||||
|
|
|
@ -53,37 +53,37 @@ export const SubscriberAdministration = ({ page }) => {
|
|||
{subscribers ? (
|
||||
<>
|
||||
<h5>Search subscribers</h5>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<input
|
||||
autoFocus
|
||||
value={q}
|
||||
onChange={(evt) => setQ(evt.target.value)}
|
||||
className="tw-daisy-input tw-w-full tw-daisy-input-bordered tw-flex tw-flex-row"
|
||||
className="tw:daisy-input tw:w-full tw:daisy-input-bordered tw:flex tw:flex-row"
|
||||
type="text"
|
||||
placeholder="Username, ID, or E-mail address"
|
||||
/>
|
||||
<button onClick={search} className="tw-daisy-btn tw-daisy-btn-primary">
|
||||
<button onClick={search} className="tw:daisy-btn tw:daisy-btn-primary">
|
||||
<SearchIcon />
|
||||
</button>
|
||||
</div>
|
||||
<table className="tw-table tw-my-4">
|
||||
<table className="tw:table tw:my-4">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="tw-text-right">Email</th>
|
||||
<th className="tw-w-12">Language</th>
|
||||
<th className="tw:text-right">Email</th>
|
||||
<th className="tw:w-12">Language</th>
|
||||
<th>Unsubscribe</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{hits.map((hit, i) => (
|
||||
<tr key={i}>
|
||||
<td className="tw-text-right">
|
||||
<td className="tw:text-right">
|
||||
<b>{hit.email}</b>
|
||||
</td>
|
||||
<td className="tw-w-12">{hit.lang.toUpperCase()}</td>
|
||||
<td className="tw-w-full">
|
||||
<td className="tw:w-12">{hit.lang.toUpperCase()}</td>
|
||||
<td className="tw:w-full">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-link"
|
||||
className="tw:daisy-btn tw:daisy-btn-link"
|
||||
onClick={() => unsubscribe(hit.ehash)}
|
||||
>
|
||||
Unsubscribe
|
||||
|
@ -96,7 +96,7 @@ export const SubscriberAdministration = ({ page }) => {
|
|||
</>
|
||||
) : (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-lg"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-lg"
|
||||
onClick={loadSubscribers}
|
||||
>
|
||||
Load Subscribers
|
||||
|
@ -127,21 +127,21 @@ export const UserAdministration = ({ Link = false }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-gap-8 tw-items-start tw-w-full">
|
||||
<div className="tw-grow">
|
||||
<div className="tw:flex tw:flex-row tw:gap-8 tw:items-start tw:w-full">
|
||||
<div className="tw:grow">
|
||||
<h5>Search users</h5>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<input
|
||||
autoFocus
|
||||
value={q}
|
||||
onChange={(evt) => setQ(evt.target.value)}
|
||||
className="tw-daisy-input tw-w-full tw-daisy-input-bordered tw-flex tw-flex-row"
|
||||
className="tw:daisy-input tw:w-full tw:daisy-input-bordered tw:flex tw:flex-row"
|
||||
type="text"
|
||||
placeholder="Username, ID, or E-mail address"
|
||||
/>
|
||||
<button
|
||||
onClick={search}
|
||||
className="tw-daisy-btn tw-daisy-btn-primary"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary"
|
||||
disabled={q.length < 3}
|
||||
>
|
||||
<SearchIcon />
|
||||
|
@ -183,9 +183,9 @@ export const User = ({ user, Link }) => {
|
|||
const { setModal } = useContext(ModalContext)
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-w-full tw-gap-4 tw-my-2">
|
||||
<div className="tw:flex tw:flex-row tw:w-full tw:gap-4 tw:my-2">
|
||||
<button
|
||||
className="tw-w-24 tw-h-24 tw-bg-base-100 tw-rounded-lg tw-shadow tw-shrink-0"
|
||||
className="tw:w-24 tw:h-24 tw:bg-base-100 tw:rounded-lg tw:shadow tw:shrink-0"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper>
|
||||
|
@ -199,18 +199,18 @@ export const User = ({ user, Link }) => {
|
|||
backgroundColor: '#ccc',
|
||||
}}
|
||||
></button>
|
||||
<div className="tw-w-full tw-flex tw-flex-col tw-gap-1">
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-flex-wrap tw-gap-1">
|
||||
<div className="tw:w-full tw:flex tw:flex-col tw:gap-1">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:flex-wrap tw:gap-1">
|
||||
<Link href={`/users/?id=${user.id}`}>{user.username}</Link>
|
||||
<KeyVal k="id" val={user.id} />
|
||||
</div>
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-flex-wrap tw-gap-1">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:flex-wrap tw:gap-1">
|
||||
<UserRole role={user.role} />
|
||||
<AccountStatus status={user.status} />
|
||||
</div>
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-flex-wrap tw-gap-1">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:flex-wrap tw:gap-1">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-sm tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-sm tw:daisy-btn-outline"
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper>
|
||||
|
@ -246,7 +246,7 @@ export const ImpersonateButton = ({ userId }) => {
|
|||
|
||||
return (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-sm tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-sm tw:daisy-btn-outline"
|
||||
onClick={impersonateUser}
|
||||
>
|
||||
Impersonate
|
||||
|
|
|
@ -12,21 +12,21 @@ export const Breadcrumbs = ({ crumbs = [], title, Link = false }) => {
|
|||
if (Link === false) Link = RegularLink
|
||||
|
||||
return (
|
||||
<div className="tw-tailwind-container tw-p-0">
|
||||
<div className="tw:tailwind-container tw:p-0">
|
||||
<ul
|
||||
className="tw-flex tw-flex-row tw-items-center tw-gap-2 tw-m-0 tw-py-4"
|
||||
className="tw:flex tw:flex-row tw:items-center tw:gap-2 tw:m-0 tw:py-4"
|
||||
style={{ paddingLeft: 0 }}
|
||||
>
|
||||
<li className="tw-inline">
|
||||
<li className="tw:inline">
|
||||
<Link href="/">Home</Link>
|
||||
</li>
|
||||
<Spacer />
|
||||
{crumbs.map((crumb, i) => (
|
||||
<li key={i} className="tw-inline">
|
||||
<li key={i} className="tw:inline">
|
||||
<Link href={crumb.href}>{crumb.label}</Link>
|
||||
</li>
|
||||
))}
|
||||
<li className="tw-inline">{title}</li>
|
||||
<li className="tw:inline">{title}</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
@ -42,4 +42,4 @@ const RegularLink = ({ href, children }) => <a href={href}>{children}</a>
|
|||
/*
|
||||
* This goes between breadcrumbs
|
||||
*/
|
||||
const Spacer = () => <li className="tw-inline">»</li>
|
||||
const Spacer = () => <li className="tw:inline">»</li>
|
||||
|
|
|
@ -19,7 +19,7 @@ export const IconButton = ({
|
|||
btnProps = {},
|
||||
}) => {
|
||||
const allProps = {
|
||||
className: `${staticLinkClasses} tw-daisy-btn-${color} hover:tw-text-${color}-content ${className}`,
|
||||
className: `${staticLinkClasses} tw:daisy-btn-${color} hover:tw:text-${color}-content ${className}`,
|
||||
title: title,
|
||||
...btnProps,
|
||||
}
|
||||
|
@ -30,5 +30,5 @@ export const IconButton = ({
|
|||
}
|
||||
|
||||
const staticLinkClasses =
|
||||
'tw-flex tw-flex-row tw-gap-2 lg:tw-gap-6 tw-items-center tw-grow ' +
|
||||
'tw-justify-between tw-w-full md:tw-w-auto tw-daisy-btn hover:tw-no-underline tw-capitalize'
|
||||
'tw:flex tw:flex-row tw:gap-2 tw:lg:gap-6 tw:items-center tw:grow ' +
|
||||
'tw:justify-between tw:w-full tw:md:w-auto tw:daisy-btn tw:hover:no-underline tw:capitalize'
|
||||
|
|
|
@ -102,8 +102,8 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-max-w-7xl tw-m-auto">
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-1 tw-justify-center tw-font-medium tw-mb-2">
|
||||
<div className="tw:max-w-7xl tw:m-auto">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-1 tw:justify-center tw:font-medium tw:mb-2">
|
||||
{Object.keys(filtered)
|
||||
.sort()
|
||||
.map((d) =>
|
||||
|
@ -111,7 +111,7 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
<button
|
||||
key={d}
|
||||
onClick={() => onClick(d)}
|
||||
className="tw-text-secondary tw-decoration-2 tw-underline tw-capitalize hover:tw-decoration-4 hover:tw-text-secondary tw-bg-transparent tw-border-0 tw-font-medium tw-p-0 tw-text-base hover:tw-cursor-pointer"
|
||||
className="tw:text-secondary tw:decoration-2 tw:underline tw:capitalize tw:hover:decoration-4 tw:hover:text-secondary tw:bg-transparent tw:border-0 tw:font-medium tw:p-0 tw:text-base tw:hover:cursor-pointer"
|
||||
>
|
||||
{d}
|
||||
</button>
|
||||
|
@ -119,7 +119,7 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
<Link
|
||||
key={d}
|
||||
href={linkBuilders[linkTo](d)}
|
||||
className="tw-text-secondary tw-decoration-2 tw-underline tw-capitalize hover:tw-decoration-4 hover:tw-text-secondary"
|
||||
className="tw:text-secondary tw:decoration-2 tw:underline tw:capitalize tw:hover:decoration-4 tw:hover:text-secondary"
|
||||
>
|
||||
{d}
|
||||
</Link>
|
||||
|
@ -128,19 +128,19 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
</div>
|
||||
{showFilters ? (
|
||||
<>
|
||||
<h6 className="tw-text-center tw-mb-0 tw-mt-4">
|
||||
<h6 className="tw:text-center tw:mb-0 tw:mt-4">
|
||||
Filters ({Object.keys(filtered).length}/{collection.length})
|
||||
</h6>
|
||||
<div className="tw-flex tw-flex-row tw-gap-1 tw-items-center tw-justify-center tw-flex-wrap tw-my-2">
|
||||
<div className="tw:flex tw:flex-row tw:gap-1 tw:items-center tw:justify-center tw:flex-wrap tw:my-2">
|
||||
<b>Tags:</b>
|
||||
{tags.map((tag) => (
|
||||
<button
|
||||
key={tag}
|
||||
className={`tw-daisy-badge tw-font-medium hover:tw-shadow hover:tw-cursor-pointer
|
||||
className={`tw:daisy-badge tw:font-medium tw:hover:shadow tw:hover:cursor-pointer
|
||||
${
|
||||
filter?.tag && Array.isArray(filter.tag) && filter.tag.includes(tag)
|
||||
? 'tw-daisy-badge-success hover:tw-daisy-badge-error'
|
||||
: 'tw-daisy-badge-primary hover:tw-daisy-badge-success'
|
||||
? 'tw:daisy-badge-success hover:tw:daisy-badge-error'
|
||||
: 'tw:daisy-badge-primary hover:tw:daisy-badge-success'
|
||||
}`}
|
||||
onClick={() => toggle('tag', tag)}
|
||||
>
|
||||
|
@ -148,16 +148,16 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-row tw-gap-1 tw-items-center tw-justify-center tw-flex-wrap tw-my-4">
|
||||
<div className="tw:flex tw:flex-row tw:gap-1 tw:items-center tw:justify-center tw:flex-wrap tw:my-4">
|
||||
<b>Techniques</b>
|
||||
{techniques.sort().map((tech) => (
|
||||
<button
|
||||
key={tech}
|
||||
className={`tw-daisy-badge tw-font-medium hover:tw-shadow
|
||||
className={`tw:daisy-badge tw:font-medium tw:hover:shadow
|
||||
${
|
||||
filter?.tech && Array.isArray(filter.tech) && filter.tech.includes(tech)
|
||||
? 'tw-daisy-badge tw-daisy-badge-success hover:tw-daisy-badge-error'
|
||||
: 'tw-daisy-badge tw-daisy-badge-accent hover:tw-daisy-badge-success'
|
||||
? 'tw:daisy-badge tw:daisy-badge-success hover:tw:daisy-badge-error'
|
||||
: 'tw:daisy-badge tw:daisy-badge-accent hover:tw:daisy-badge-success'
|
||||
}`}
|
||||
onClick={() => toggle('tech', tech)}
|
||||
>
|
||||
|
@ -165,39 +165,39 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-justify-center tw-flex-wrap tw-my-4">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:justify-center tw:flex-wrap tw:my-4">
|
||||
<b>Difficulty:</b>
|
||||
{[1, 2, 3, 4, 5].map((score) => (
|
||||
<button
|
||||
onClick={() => updateFilter('difficulty', score)}
|
||||
key={score}
|
||||
className={`tw-daisy-btn tw-daisy-btn-sm ${
|
||||
className={`tw:daisy-btn tw:daisy-btn-sm ${
|
||||
filter.difficulty === score
|
||||
? 'tw-daisy-btn-secondary tw-daisy-btn-outline'
|
||||
: 'tw-daisy-btn-ghost'
|
||||
? 'tw:daisy-btn-secondary tw:daisy-btn-outline'
|
||||
: 'tw:daisy-btn-ghost'
|
||||
}`}
|
||||
>
|
||||
<Difficulty score={score} />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-items-center tw-justify-center tw-flex-wrap tw-my-2">
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:items-center tw:justify-center tw:flex-wrap tw:my-2">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline"
|
||||
onClick={() => updateFilter('example', !filter.example)}
|
||||
>
|
||||
{filter.example ? <CisFemaleIcon /> : <ShowcaseIcon />}
|
||||
{filter.example ? 'Show Line Drawings' : 'Show Examples'}
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline"
|
||||
onClick={() => setFilter({ example: 1 })}
|
||||
>
|
||||
<ResetIcon />
|
||||
Clear Filter
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline"
|
||||
onClick={() => setShowFilters(false)}
|
||||
>
|
||||
<FilterIcon />
|
||||
|
@ -206,16 +206,16 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-items-center tw-justify-center tw-flex-wrap tw-my-2">
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:items-center tw:justify-center tw:flex-wrap tw:my-2">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline"
|
||||
onClick={() => updateFilter('example', !filter.example)}
|
||||
>
|
||||
{filter.example ? <CisFemaleIcon /> : <ShowcaseIcon />}
|
||||
{filter.example ? 'Show Line Drawings' : 'Show Examples'}
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline"
|
||||
onClick={() => setShowFilters(true)}
|
||||
>
|
||||
<FilterIcon />
|
||||
|
@ -225,7 +225,7 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
)}
|
||||
</div>
|
||||
<div
|
||||
className={`tw-grid tw-grid-cols-2 tw-gap-2 tw-mt-4 tw-justify-center sm:tw-grid-cols-3 md:tw-grid-cols-4 ${editor ? 'lg:tw-grid-cols-6 2xl:tw-grid-cols-12' : ''} tw-mb-8`}
|
||||
className={`tw:grid tw:grid-cols-2 tw:gap-2 tw:mt-4 tw:justify-center tw:sm:grid-cols-3 tw:md:grid-cols-4 ${editor ? 'tw:lg:grid-cols-6 tw:2xl:grid-cols-12' : ''} tw:mb-8`}
|
||||
>
|
||||
{Object.keys(filtered)
|
||||
.sort()
|
||||
|
@ -253,7 +253,7 @@ export const Collection = ({ Link = false, linkTo = 'about', editor = false, onC
|
|||
const Technique = ({ Link = WebLink, technique }) => (
|
||||
<Link
|
||||
href={`/designs/techniques/${technique}`}
|
||||
className="tw-daisy-badge tw-daisy-badge-accent hover:tw-daisy-badge-secondary hover:tw-shadow tw-font-medium"
|
||||
className="tw:daisy-badge tw:daisy-badge-accent hover:tw:daisy-badge-secondary tw:hover:shadow tw:font-medium"
|
||||
>
|
||||
{technique}
|
||||
</Link>
|
||||
|
@ -269,7 +269,7 @@ const Technique = ({ Link = WebLink, technique }) => (
|
|||
const Tag = ({ Link = WebLink, technique }) => (
|
||||
<Link
|
||||
href={`/designs/tags/${tag}`}
|
||||
className="tw-daisy-badge tw-daisy-badge-primary hover:tw-daisy-badge-secondary hover:tw-shadow tw-font-medium"
|
||||
className="tw:daisy-badge tw:daisy-badge-primary hover:tw:daisy-badge-secondary tw:hover:shadow tw:font-medium"
|
||||
>
|
||||
{tag}
|
||||
</Link>
|
||||
|
@ -292,28 +292,28 @@ const DesignCard = ({ name, lineDrawing = false, linkTo, Link, onClick }) => {
|
|||
|
||||
const inner = (
|
||||
<div
|
||||
className={`tw-flex tw-flex-col tw-flex-nowrap tw-items-start tw-justify-between tw-gap-2 tw-border-neutral-500 group-hover:tw-border-secondary
|
||||
tw-w-full tw-h-full tw-border tw-border-2 tw-border-solid tw-p-0 tw-relative tw-rounded-lg tw-rounded-lg`}
|
||||
className={`tw:flex tw:flex-col tw:flex-nowrap tw:items-start tw:justify-between tw:gap-2 tw:border-neutral-500 tw:group-hover:border-secondary
|
||||
tw:w-full tw:h-full tw:border tw:border-2 tw:border-solid tw:p-0 tw:relative tw:rounded-lg tw:rounded-lg`}
|
||||
style={bg}
|
||||
>
|
||||
<h5
|
||||
className={`tw-text-center tw-py-2 tw-px-4 tw-rounded-t tw-m-0 tw-w-full group-hover:tw-no-underline group-hover:tw-bg-secondary group-hover:tw-bg-opacity-70
|
||||
${lineDrawing ? '' : 'tw-bg-neutral tw-text-neutral-content tw-bg-opacity-80'}`}
|
||||
className={`tw:text-center tw:py-2 tw:px-4 tw:rounded-t tw:m-0 tw:w-full tw:group-hover:no-underline tw:group-hover:bg-secondary/70
|
||||
${lineDrawing ? '' : 'tw:bg-neutral/80 tw:text-neutral-content'}`}
|
||||
>
|
||||
{about[name].name}
|
||||
</h5>
|
||||
{lineDrawing ? (
|
||||
<div className="tw-p-1 tw-grow tw-w-full tw-h-auto tw-square tw-text-center">
|
||||
<LineDrawing className="tw-max-w-full tw-m-auto tw-my-4 tw-text-base-content" />
|
||||
<div className="tw:p-1 tw:grow tw:w-full tw:h-auto tw:square tw:text-center">
|
||||
<LineDrawing className="tw:max-w-full tw:m-auto tw:my-4 tw:text-base-content" />
|
||||
</div>
|
||||
) : (
|
||||
<span />
|
||||
)}
|
||||
<div
|
||||
className={`tw-flex tw-flex-row tw-items-center tw-justify-center tw-py-1 tw-px-2 tw-rounded-b tw-m-0 tw-w-full
|
||||
${lineDrawing ? '' : `tw-text-neutral-content`}`}
|
||||
className={`tw:flex tw:flex-row tw:items-center tw:justify-center tw:py-1 tw:px-2 tw:rounded-b tw:m-0 tw:w-full
|
||||
${lineDrawing ? '' : `tw:text-neutral-content`}`}
|
||||
>
|
||||
<Difficulty score={about[name].difficulty} className="group-hover:tw-text-secondary" />
|
||||
<Difficulty score={about[name].difficulty} className="tw:group-hover:text-secondary" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -321,7 +321,7 @@ const DesignCard = ({ name, lineDrawing = false, linkTo, Link, onClick }) => {
|
|||
return onClick ? (
|
||||
<button
|
||||
onClick={() => onClick(name)}
|
||||
className="hover:tw-bg-secondary hover:tw-bg-opacity-10 tw-rounded-lg tw-group hover:tw-no-underline tw-bg-transparent tw-border-0 hover:tw-cursor-pointer tw-p-0"
|
||||
className="tw:hover:bg-secondary/10 tw:rounded-lg tw:group tw:hover:no-underline tw:bg-transparent tw:border-0 tw:hover:cursor-pointer tw:p-0"
|
||||
title={about[name].description}
|
||||
>
|
||||
{inner}
|
||||
|
@ -329,7 +329,7 @@ const DesignCard = ({ name, lineDrawing = false, linkTo, Link, onClick }) => {
|
|||
) : (
|
||||
<Link
|
||||
href={linkBuilders[linkTo](name)}
|
||||
className="hover:tw-bg-secondary hover:tw-bg-opacity-10 tw-rounded-lg tw-group hover:tw-no-underline"
|
||||
className="tw:hover:bg-secondary/10 tw:rounded-lg tw:group tw:hover:no-underline"
|
||||
title={about[name].description}
|
||||
>
|
||||
{inner}
|
||||
|
@ -344,9 +344,9 @@ const DesignCard = ({ name, lineDrawing = false, linkTo, Link, onClick }) => {
|
|||
* @param {number} props.score - The difficulty score of the design (1-5)
|
||||
*/
|
||||
const Difficulty = ({ score = 0, className = '' }) => (
|
||||
<div className={`tw-flex tw-flex-row tw-items-center ${className}`}>
|
||||
<div className={`tw:flex tw:flex-row tw:items-center ${className}`}>
|
||||
{[0, 1, 2, 3, 4].map((i) => (
|
||||
<CircleIcon key={i} fill={i < score ? true : false} className={`tw-w-4 tw-h-4`} />
|
||||
<CircleIcon key={i} fill={i < score ? true : false} className={`tw:w-4 tw:h-4`} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
|
@ -400,9 +400,9 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
}
|
||||
|
||||
const makeButton = (
|
||||
<div className={`tw-grid tw-grid-cols-1 tw-gap-2 tw-mb-4`}>
|
||||
<div className={`tw:grid tw:grid-cols-1 tw:gap-2 tw:mb-4`}>
|
||||
<IconButton href={`/editor/#s={"design"%3A"${design}"%2C"view"%3A"draft"}`} color="primary">
|
||||
<NewPatternIcon className="tw-w-8 tw-h-8" />
|
||||
<NewPatternIcon className="tw:w-8 tw:h-8" />
|
||||
New {capitalize(design)} pattern
|
||||
</IconButton>
|
||||
</div>
|
||||
|
@ -410,9 +410,9 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
const buttons = noDocsLink ? (
|
||||
makeButton
|
||||
) : (
|
||||
<div className={`tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-2 tw-mb-4`}>
|
||||
<div className={`tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-2 tw:mb-4`}>
|
||||
<IconButton href={`/docs/designs/${design}`} color="secondary">
|
||||
<DocsIcon className="tw-w-8 tw-h-8" />
|
||||
<DocsIcon className="tw:w-8 tw:h-8" />
|
||||
Documentation
|
||||
</IconButton>
|
||||
{makeButton}
|
||||
|
@ -421,15 +421,15 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="lg:tw-hidden">{buttons}</div>
|
||||
<div className={`tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-2`}>
|
||||
<div className="tw-relative">
|
||||
<div className="tw tw-top-0 tw-left-0">
|
||||
<div className="tw:lg:hidden">{buttons}</div>
|
||||
<div className={`tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-2`}>
|
||||
<div className="tw:relative">
|
||||
<div className="tw tw:top-0 tw:left-0">
|
||||
{back ? <LineDrawingBack /> : <LineDrawing />}
|
||||
</div>
|
||||
{LineDrawingBack ? (
|
||||
<button
|
||||
className="tw-absolute tw-top-2 tw-right-4 tw-start-auto tw-daisy-btn tw-daisy-btn-neutral tw-daisy-btn-outline tw-daisy-btn-xs"
|
||||
className="tw:absolute tw:top-2 tw:right-4 tw:start-auto tw:daisy-btn tw:daisy-btn-neutral tw:daisy-btn-outline tw:daisy-btn-xs"
|
||||
onClick={() => setBack(!back)}
|
||||
>
|
||||
{back ? 'Front' : 'Back'} view
|
||||
|
@ -437,11 +437,11 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
) : null}
|
||||
</div>
|
||||
<div className="">
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">Description</div>
|
||||
<span className="tw-text-xl">{about[design].description}</span>
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">Description</div>
|
||||
<span className="tw:text-xl">{about[design].description}</span>
|
||||
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">By</div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-1 items-center">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">By</div>
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-1 items-center">
|
||||
{codeBy.map((code) => (
|
||||
<KeyVal key={code} k="code" val={code} color="secondary" />
|
||||
))}
|
||||
|
@ -450,12 +450,12 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
))}
|
||||
</div>
|
||||
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">Difficulty</div>
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">Difficulty</div>
|
||||
<Difficulty score={about[design].difficulty} />
|
||||
|
||||
{optionalMeasurements[design].length > 0 ? (
|
||||
<>
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">
|
||||
Optional Measurements
|
||||
</div>
|
||||
<div className="">
|
||||
|
@ -477,7 +477,7 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
|
||||
{requiredMeasurements[design].length > 0 ? (
|
||||
<>
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">
|
||||
Required Measurements
|
||||
</div>
|
||||
<div className="">
|
||||
|
@ -497,24 +497,24 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
</>
|
||||
) : null}
|
||||
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">Tags</div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-1 items-center">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">Tags</div>
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-1 items-center">
|
||||
{tags.map((tag) => (
|
||||
<Link
|
||||
key={tag}
|
||||
className="tw-daisy-badge tw-daisy-badge-primary tw-font-medium hover:tw-shadow hover:tw-cursor-pointer"
|
||||
className="tw:daisy-badge tw:daisy-badge-primary tw:font-medium tw:hover:shadow tw:hover:cursor-pointer"
|
||||
href={`/designs/#filter={"example"%3Atrue%2C"tag"%3A["${tag}"]}`}
|
||||
>
|
||||
{tag}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">Techniques</div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-1 items-center">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">Techniques</div>
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-1 items-center">
|
||||
{techniques.map((tech) => (
|
||||
<Link
|
||||
key={tech}
|
||||
className="tw-daisy-badge tw-daisy-badge-accent tw-font-medium hover:tw-shadow hover:tw-cursor-pointer"
|
||||
className="tw:daisy-badge tw:daisy-badge-accent tw:font-medium tw:hover:shadow tw:hover:cursor-pointer"
|
||||
href={`/designs/#filter={"example"%3Atrue%2C"tag"%3A["${tech}"]}`}
|
||||
>
|
||||
{tech}
|
||||
|
@ -522,8 +522,8 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
))}
|
||||
</div>
|
||||
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">Examples</div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-1 items-center">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">Examples</div>
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-1 items-center">
|
||||
<KeyVal
|
||||
k="FreeSewing"
|
||||
val="showcase"
|
||||
|
@ -539,8 +539,8 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="tw-mt-2 tw-text-sm tw-opacity-70 tw-font-medium">Documentation</div>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-1 items-center">
|
||||
<div className="tw:mt-2 tw:text-sm tw:opacity-70 tw:font-medium">Documentation</div>
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-1 items-center">
|
||||
<Link href={`/docs/designs/${design}/#notes`}>Designer Notes</Link>,
|
||||
<Link href={`/docs/designs/${design}/#needs`}>What You Need</Link>,
|
||||
<Link href={`/docs/designs/${design}/#fabric`}>Fabric Options</Link>,
|
||||
|
@ -548,7 +548,7 @@ export const DesignInfo = ({ Link = false, design = false, noDocsLink = false })
|
|||
<Link href={`/docs/designs/${design}/options/`}>Design Options</Link>,
|
||||
<Link href={`/docs/designs/${design}/instructions/`}>Sewing Instructions</Link>
|
||||
</div>
|
||||
<div className="tw-my-4">{buttons}</div>
|
||||
<div className="tw:my-4">{buttons}</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
@ -572,391 +572,3 @@ const SharingIsCaring = ({ design }) => (
|
|||
<p>If you like, you can copy the hashtag below:</p>
|
||||
</>
|
||||
)
|
||||
|
||||
/*
|
||||
// __SDEFILE__ - This file is a dependency for the stand-alone environment
|
||||
// Dependencies
|
||||
import {
|
||||
nsMerge,
|
||||
capitalize,
|
||||
optionsMenuStructure,
|
||||
optionType,
|
||||
cloudflareImageUrl,
|
||||
horFlexClasses,
|
||||
} from 'shared/utils.mjs'
|
||||
import { designs } from 'shared/config/designs.mjs'
|
||||
import { examples } from 'site/components/design-examples.mjs'
|
||||
// Hooks
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useDesign } from 'site/hooks/use-design.mjs'
|
||||
import { useContext, Fragment } from 'react'
|
||||
// Context
|
||||
import { ModalContext } from 'shared/context/modal-context.mjs'
|
||||
// Components
|
||||
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
||||
import { lineDrawings } from 'shared/components/designs/linedrawings/index.mjs'
|
||||
import { Difficulty } from 'shared/components/designs/difficulty.mjs'
|
||||
import { PageLink, AnchorLink, Link } from 'shared/components/link.mjs'
|
||||
import { DocsLink, DocsTitle } from 'shared/components/mdx/docs-helpers.mjs'
|
||||
import { Popout } from 'shared/components/popout/index.mjs'
|
||||
import { NewPatternIcon, DocsIcon } from 'shared/components/icons.mjs'
|
||||
import { DynamicMdx } from 'shared/components/mdx/dynamic.mjs'
|
||||
|
||||
// Translation namespaces used on this page
|
||||
export const ns = nsMerge(
|
||||
'account',
|
||||
'tags',
|
||||
'techniques',
|
||||
'measurements',
|
||||
'workbench',
|
||||
'designs',
|
||||
'tags'
|
||||
)
|
||||
|
||||
const Option = ({ id, option, design }) =>
|
||||
optionType(option) === 'constant' ? null : (
|
||||
<li key={option.name}>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/options/${id.toLowerCase()}`} />
|
||||
</li>
|
||||
)
|
||||
|
||||
const OptionGroup = ({ id, group, t, design }) => (
|
||||
<li key={id}>
|
||||
<b>{t(`workbench:${id}`)}</b>
|
||||
<ul className="list list-inside list-disc pl-2">
|
||||
{Object.entries(group).map(([sid, entry]) =>
|
||||
entry.isGroup ? (
|
||||
<OptionGroup id={sid} key={sid} t={t} group={entry} design={design} />
|
||||
) : (
|
||||
<Option key={sid} id={sid} option={entry} design={design} />
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</li>
|
||||
)
|
||||
export const SimpleOptionsList = ({ options, t, design }) => {
|
||||
const structure = optionsMenuStructure(options, {}, true)
|
||||
const output = []
|
||||
for (const [key, entry] of Object.entries(structure)) {
|
||||
const shared = { key, t, design, id: key }
|
||||
if (entry.isGroup) output.push(<OptionGroup {...shared} group={entry} />)
|
||||
else output.push(<Option {...shared} option={entry} />)
|
||||
}
|
||||
|
||||
return <ul className="list list-inside pl-2 list-disc">{output}</ul>
|
||||
}
|
||||
|
||||
export const DesignInfo = ({ design, docs = false, workbench = false, modal = false }) => {
|
||||
const { setModal } = useContext(ModalContext)
|
||||
const { t, i18n } = useTranslation([...ns, design])
|
||||
const { language } = i18n
|
||||
const Design = useDesign(design)
|
||||
const config = Design.patternConfig
|
||||
|
||||
// Translate measurements
|
||||
const measies = { required: {}, optional: {} }
|
||||
if (config?.measurements) {
|
||||
for (const m of config.measurements) measies.required[m] = t(`measurements:${m}`)
|
||||
}
|
||||
if (config?.optionalMeasurements) {
|
||||
for (const m of config.optionalMeasurements) measies.optional[m] = t(`measurements:${m}`)
|
||||
}
|
||||
|
||||
// Linedrawing
|
||||
const LineDrawing = lineDrawings[design]
|
||||
? lineDrawings[design]
|
||||
: ({ className }) => <div className={className}></div>
|
||||
|
||||
// Docs content
|
||||
const docsContent = (
|
||||
<>
|
||||
<h2 id="docs">{t('account:docs')}</h2>
|
||||
<ul className="list list-disc list-inside pl-2">
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}`} />
|
||||
</li>
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/cutting`} />
|
||||
</li>
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/instructions`} />
|
||||
</li>
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/needs`} />
|
||||
</li>
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/fabric`} />
|
||||
</li>
|
||||
{Object.keys(config.options).length > 0 ? (
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/options`} />
|
||||
</li>
|
||||
) : null}
|
||||
<li>
|
||||
<DocsLink site="org" slug={`docs/designs/${design}/notes`} />
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<h5 className="-mt-6 text-accent font-medium">#FreeSewing{capitalize(design)}</h5>
|
||||
<p className="text-xl">{t(`designs:${design}.d`)}</p>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
|
||||
{workbench ? null : (
|
||||
<Link
|
||||
className={`${horFlexClasses} btn btn-primary btn-lg flex md:hidden`}
|
||||
href={`/new/${design}`}
|
||||
>
|
||||
<NewPatternIcon className="w-8 h-8" />
|
||||
{t('tags:newThingPattern', { thing: capitalize(design) })}
|
||||
</Link>
|
||||
)}
|
||||
{docs ? null : (
|
||||
<Link
|
||||
className={`${horFlexClasses} btn btn-secondary btn-lg flex md:hidden`}
|
||||
href={`/docs/designs/${design}`}
|
||||
>
|
||||
<DocsIcon className="w-8 h-8" />
|
||||
{t('account:docs')}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
{docs || workbench || modal ? null : (
|
||||
<div className="flex flex-row flex-wrap gap-2 md:gap-4 items-center p-4 border rounded-lg bg-secondary bg-opacity-5 max-w-4xl">
|
||||
<b>Jump to:</b>
|
||||
<AnchorLink id="notes">
|
||||
<DocsTitle
|
||||
slug={`docs/designs/${design}/notes`}
|
||||
language={language}
|
||||
format={(t) => t.split(':').pop().trim()}
|
||||
/>
|
||||
</AnchorLink>
|
||||
{examples && <AnchorLink id="examples" txt={t('acount:examples')} />}
|
||||
{['needs', 'fabric'].map((page) => (
|
||||
<AnchorLink id={page} key={page}>
|
||||
<DocsTitle
|
||||
slug={`docs/designs/${design}/${page}`}
|
||||
language={language}
|
||||
format={(t) => t.split(':').pop().trim()}
|
||||
/>
|
||||
</AnchorLink>
|
||||
))}
|
||||
<AnchorLink id="docs" txt={t('account:docs')} />
|
||||
<AnchorLink id="specs" txt={t('account:specifications')} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={`mt-8 w-full ${docs ? '' : 'flex flex-row flex-wrap justify-between'}`}>
|
||||
<div className={`w-full max-w-2xl ${docs ? '' : 'md:w-2/3 pr-0 md:pr-8'}`}>
|
||||
<LineDrawing className="w-full text-base-content" />
|
||||
{docs ? null : (
|
||||
<>
|
||||
<h2 id="notes">
|
||||
<DocsTitle
|
||||
slug={`docs/designs/${design}/notes`}
|
||||
language={language}
|
||||
format={(t) => t.split(':').pop().trim()}
|
||||
/>
|
||||
</h2>
|
||||
<DynamicMdx
|
||||
site="org"
|
||||
slug={`docs/designs/${design}/notes`}
|
||||
language={language}
|
||||
title={false}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{docs ? docsContent : null}
|
||||
{examples ? (
|
||||
<>
|
||||
<h2 id="examples">{t('account:examples')}</h2>
|
||||
{examples[design] ? (
|
||||
<div className="grid grid-cols-2 gap-2 md:grid-cols-3 lg:grid-cols-3">
|
||||
{examples[design].map((ex) => (
|
||||
<button
|
||||
key={ex}
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<ModalWrapper
|
||||
flex="col"
|
||||
justify="top lg:justify-center"
|
||||
slideFrom="right"
|
||||
>
|
||||
<img
|
||||
className="w-full shadow rounded-lg"
|
||||
src={cloudflareImageUrl({ id: `showcase-${ex}`, variant: 'public' })}
|
||||
/>
|
||||
<p className="text-center">
|
||||
<PageLink href={`/showcase/${ex}`} txt={t('account:visitShowcase')} />
|
||||
</p>
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
>
|
||||
<img
|
||||
className="w-full shadow rounded-lg"
|
||||
src={cloudflareImageUrl({ id: `showcase-${ex}`, variant: 'sq500' })}
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<Popout note>
|
||||
<h5>{t('account:noExamples')}</h5>
|
||||
<p>{t('account:noExamplesMsg')}</p>
|
||||
<p className="text-right">
|
||||
<Link className="btn btn-primary" href="/new/showcase">
|
||||
{t('account:showcaseNew')}
|
||||
</Link>
|
||||
</p>
|
||||
</Popout>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
{docs
|
||||
? null
|
||||
: ['needs', 'fabric'].map((page) => (
|
||||
<Fragment key={page}>
|
||||
<h2 id={page}>
|
||||
<DocsTitle
|
||||
slug={`docs/designs/${design}/${page}`}
|
||||
language={language}
|
||||
format={(t) => t.split(':').pop().trim()}
|
||||
/>
|
||||
</h2>
|
||||
<DynamicMdx
|
||||
site="org"
|
||||
slug={`docs/designs/${design}/${page}`}
|
||||
language={language}
|
||||
title={false}
|
||||
/>
|
||||
</Fragment>
|
||||
))}
|
||||
|
||||
{docs ? null : docsContent}
|
||||
</div>
|
||||
|
||||
<div className={`w-full ${docs ? '' : 'md:w-1/3'}`}>
|
||||
{workbench ? null : (
|
||||
<Link
|
||||
className={`${horFlexClasses} btn btn-primary btn-lg hidden md:flex mb-2`}
|
||||
href={`/new/${design}`}
|
||||
>
|
||||
<NewPatternIcon className="w-8 h-8" />
|
||||
{t('tags:newThingPattern', { thing: capitalize(design) })}
|
||||
</Link>
|
||||
)}
|
||||
{docs ? null : (
|
||||
<Link
|
||||
className={`${horFlexClasses} btn btn-secondary btn-lg hidden md:flex`}
|
||||
href={`/docs/designs/${design}`}
|
||||
>
|
||||
<DocsIcon className="w-8 h-8" />
|
||||
{t('account:docs')}
|
||||
</Link>
|
||||
)}
|
||||
<h2 id="specs">{t('account:specifications')}</h2>
|
||||
|
||||
<h6 className="mt-4">{t('account:design')}</h6>
|
||||
<ul>
|
||||
{designs[design].design.map((person) => (
|
||||
<li key={person}>{person}</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<h6 className="mt-4">{t('account:code')}</h6>
|
||||
<ul>
|
||||
{designs[design].code.map((person) => (
|
||||
<li key={person}>{person}</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<h6 className="mt-4">{t('tags:difficulty')}</h6>
|
||||
<Difficulty score={designs[design].difficulty} />
|
||||
|
||||
<h6 className="mt-4">{t('tags:tags')}</h6>
|
||||
<div className="flex flex-row flex-wrap items-center gap-1">
|
||||
{designs[design].tags.map((tag) => (
|
||||
<span className="badge badge-primary font-medium" key={tag}>
|
||||
{t(`tags:${tag}`)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h6 className="mt-4">{t('techniques:techniques')}</h6>
|
||||
<div className="flex flex-row flex-wrap items-center gap-1">
|
||||
{designs[design].techniques.map((tech) => (
|
||||
<span className="badge badge-accent font-medium" key={tech}>
|
||||
{t(`techniques:${tech}`)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{Object.keys(measies.required).length > 0 ? (
|
||||
<>
|
||||
<h6 className="mt-4">{t('account:requiredMeasurements')}</h6>
|
||||
<ul className="list list-disc list-inside pl-2">
|
||||
{Object.keys(measies.required)
|
||||
.sort()
|
||||
.map((m) => (
|
||||
<li key={m}>
|
||||
<PageLink
|
||||
href={`/docs/measurements/${m.toLowerCase()}`}
|
||||
txt={measies.required[m]}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{Object.keys(measies.optional).length > 0 ? (
|
||||
<>
|
||||
<h6 className="mt-4">{t('account:optionalMeasurements')}</h6>
|
||||
<ul className="list list-disc list-inside pl-2">
|
||||
{Object.keys(measies.optional)
|
||||
.sort()
|
||||
.map((m) => (
|
||||
<li key={m}>
|
||||
<PageLink
|
||||
href={`/docs/measurements/${m.toLowerCase()}`}
|
||||
txt={measies.optional[m]}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{Object.keys(config.options).length > 0 ? (
|
||||
<>
|
||||
<h6 className="mt-4">{t('account:designOptions')}</h6>
|
||||
<SimpleOptionsList options={config.options} t={t} design={design} />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<h6 className="mt-4">{t('account:parts')}</h6>
|
||||
<ul className="list list-disc list-inside pl-2">
|
||||
{config.draftOrder.map((part) => (
|
||||
<li key={part}>{part}</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{Object.keys(config.plugins).length > 0 ? (
|
||||
<>
|
||||
<h6 className="mt-4">{t('account:plugins')}</h6>
|
||||
<ul className="list list-disc list-inside pl-2">
|
||||
{Object.keys(config.plugins).map((plugin) => (
|
||||
<li key={plugin}>{plugin}</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -4,11 +4,11 @@ import { BulletIcon } from '@freesewing/react/components/Icon'
|
|||
|
||||
export const ControlScore = ({ control, color = 'base-content' }) =>
|
||||
control ? (
|
||||
<div className={`tw-flex tw-flex-row tw-items-center tw-text-${color}`}>
|
||||
<div className={`tw:flex tw:flex-row tw:items-center tw:text-${color}`}>
|
||||
{Object.keys(controlDesc).map((score) => (
|
||||
<BulletIcon
|
||||
fill={control >= score ? true : false}
|
||||
className="tw-w-6 tw-h-6 tw--ml-1"
|
||||
className="tw:w-6 tw:h-6 tw:-ml-1"
|
||||
key={score}
|
||||
/>
|
||||
))}
|
||||
|
|
|
@ -25,20 +25,20 @@ export const CopyToClipboardButton = ({ children, content, label = false, sup =
|
|||
const [copied, setCopied] = useState(false)
|
||||
const { setLoadingStatus } = useContext(LoadingStatusContext)
|
||||
|
||||
const style = sup ? 'tw-w-4 tw-h-4 tw--mt-4' : 'tw-w-5 tw-h-5'
|
||||
const style = sup ? 'tw:w-4 tw:h-4 tw:-mt-4' : 'tw:w-5 tw:h-5'
|
||||
|
||||
return (
|
||||
<button
|
||||
className={(copied ? 'tw-text-success ' : '') + 'tw-daisy-btn tw-w-full lg:tw-w-auto'}
|
||||
className={(copied ? 'tw:text-success ' : '') + 'tw:daisy-btn tw:w-full tw:lg:w-auto'}
|
||||
onClick={() => handleCopied(content, setCopied, setLoadingStatus, label)}
|
||||
>
|
||||
{copied ? (
|
||||
<OkIcon
|
||||
className={`${style} tw-text-success-content tw-bg-success tw-rounded-full tw-p-1`}
|
||||
className={`${style} tw:text-success-content tw:bg-success tw:rounded-full tw:p-1`}
|
||||
stroke={4}
|
||||
/>
|
||||
) : (
|
||||
<CopyIcon className={`${style} tw-text-inherit`} />
|
||||
<CopyIcon className={`${style} tw:text-inherit`} />
|
||||
)}
|
||||
{children}
|
||||
</button>
|
||||
|
|
|
@ -45,9 +45,9 @@ export const CuratedSetLineup = ({ href = false, clickHandler = false, Link = fa
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`tw-w-full tw-flex tw-flex-row ${
|
||||
sets.length > 1 ? 'tw-justify-start tw-px-8' : 'tw-justify-center'
|
||||
} tw-overflow-x-scroll`}
|
||||
className={`tw:w-full tw:flex tw:flex-row ${
|
||||
sets.length > 1 ? 'tw:justify-start tw:px-8' : 'tw:justify-center'
|
||||
} tw:overflow-x-scroll`}
|
||||
style={{
|
||||
backgroundImage: `url(/img/lineup-backdrop.svg)`,
|
||||
width: 'auto',
|
||||
|
@ -58,7 +58,7 @@ export const CuratedSetLineup = ({ href = false, clickHandler = false, Link = fa
|
|||
{sets.map((set) => {
|
||||
const props = {
|
||||
className:
|
||||
'tw-aspect-[1/3] tw-w-auto tw-h-96 tw-bg-transparent tw-border-0 hover:tw-cursor-pointer hover:tw-bg-secondary/20',
|
||||
'tw:aspect-1/3 tw:w-auto tw:h-96 tw:bg-transparent tw:border-0 tw:hover:cursor-pointer tw:hover:bg-secondary/20',
|
||||
style: {
|
||||
backgroundImage: `url(${cloudflareImageUrl({
|
||||
id: `cset-${set.id}`,
|
||||
|
@ -73,7 +73,7 @@ export const CuratedSetLineup = ({ href = false, clickHandler = false, Link = fa
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-col tw-items-center" key={set.id}>
|
||||
<div className="tw:flex tw:flex-col tw:items-center" key={set.id}>
|
||||
{typeof clickHandler === 'function' ? (
|
||||
<button {...props} onClick={() => clickHandler(set)}></button>
|
||||
) : null}
|
||||
|
@ -118,14 +118,14 @@ export const CuratedSet = ({ Link = false, id = false }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<h2 className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<h2 className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
{set.nameEn} <KeyVal k="id" val={set.id} />
|
||||
</h2>
|
||||
<Markdown>{set.notesEn}</Markdown>
|
||||
<h2>Image</h2>
|
||||
<img src={cloudflareImageUrl({ id: `cset-${set.id}`, variant: 'public' })} />
|
||||
<h2>Measurements</h2>
|
||||
<table className="tw-table">
|
||||
<table className="tw:table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Measurement</th>
|
||||
|
@ -144,7 +144,7 @@ export const CuratedSet = ({ Link = false, id = false }) => {
|
|||
'asc'
|
||||
).map((entry) => (
|
||||
<tr key={entry.id}>
|
||||
<td className="tw-text-right">{entry.t}</td>
|
||||
<td className="tw:text-right">{entry.t}</td>
|
||||
<td>{isDegreeMeasurement(entry.id) ? `${entry.val}°` : formatMm(entry.val)}</td>
|
||||
<td
|
||||
dangerouslySetInnerHTML={{
|
||||
|
|
|
@ -88,7 +88,7 @@ export const DesignCard = ({ name, lineDrawing = false }) => {
|
|||
>
|
||||
<h5
|
||||
className={`text-center py-2 px-4 rounded-t-lg m-0 w-full
|
||||
${lineDrawing ? '' : 'bg-neutral text-neutral-content bg-opacity-70'}`}
|
||||
${lineDrawing ? '' : 'bg-neutral/70 text-neutral-content'}`}
|
||||
>
|
||||
{t(`designs:${name}.t`)}
|
||||
</h5>
|
||||
|
@ -97,11 +97,7 @@ export const DesignCard = ({ name, lineDrawing = false }) => {
|
|||
</div>
|
||||
<div
|
||||
className={`pt-0 m-0 -mt-2 text-center w-full
|
||||
${
|
||||
lineDrawing
|
||||
? 'bg-transparent text-base-content'
|
||||
: 'bg-neutral text-neutral-content bg-opacity-70'
|
||||
}`}
|
||||
${lineDrawing ? 'bg-transparent text-base-content' : 'bg-neutral/70 text-neutral-content'}`}
|
||||
></div>
|
||||
</div>
|
||||
</button>
|
||||
|
|
|
@ -120,12 +120,12 @@ const AccountNavbarItem = ({ Link }) => {
|
|||
|
||||
const SimpleNavbarItem = ({ label, Icon, href, Link }) => (
|
||||
<Link
|
||||
className="tw-daisy-btn tw-daisy-btn-ghost hover:tw-no-underline hover:tw-text-base-content custom-navbar-item"
|
||||
className="tw:daisy-btn tw:daisy-btn-ghost tw:hover:no-underline tw:hover:text-base-content custom-navbar-item no-hover-decoration"
|
||||
href={href}
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<Icon className="tw-w-6 tw-h-6" />
|
||||
<span className="tw-text-lg">{label}</span>
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
<Icon className="tw:w-6 tw:h-6 tw:text-base-content" />
|
||||
<span className="tw:text-lg tw:text-base-content">{label}</span>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
|
|
|
@ -5,19 +5,15 @@ import React, { useState } from 'react'
|
|||
* So instead, we handle this in React state
|
||||
*/
|
||||
const getProps = (isActive = false) => ({
|
||||
className: `tw-p-2 tw-px-4 tw-rounded-lg tw-bg-transparent tw-shadow hover:tw-cursor-pointer
|
||||
tw-w-full tw-h-auto tw-content-start tw-text-left tw-bg-opacity-20
|
||||
${isActive ? 'hover:tw-bg-transparent' : 'hover:tw-bg-secondary hover:tw-bg-opacity-10'}`,
|
||||
className: `tw:p-2 tw:px-4 tw:rounded-lg tw:bg-transparent tw:shadow tw:hover:cursor-pointer
|
||||
tw:w-full tw:h-auto tw:content-start tw:text-left
|
||||
${isActive ? 'tw:hover:bg-transparent' : 'tw:hover:bg-secondary/10'}`,
|
||||
})
|
||||
|
||||
const getSubProps = (isActive) => ({
|
||||
className: `tw-p-2 tw-px-4 tw-rounded-none tw-bg-transparent tw-w-full tw-h-auto
|
||||
tw-content-start tw-bg-secondary tw-text-left tw-bg-opacity-20
|
||||
${
|
||||
isActive
|
||||
? 'tw-bg-opacity-100 hover:tw-bg-transparent tw-shadow'
|
||||
: 'hover:tw-bg-opacity-10 hover:tw-bg-secondary '
|
||||
}`,
|
||||
className: `tw:p-2 tw:px-4 tw:rounded-none tw:bg-transparent tw:w-full tw:h-auto
|
||||
tw:content-start tw:bg-secondary/20 tw:text-left
|
||||
${isActive ? 'tw:bg-secondary tw:hover:bg-transparent tw:shadow' : 'tw:hover:bg-secondary/10 '}`,
|
||||
})
|
||||
|
||||
const components = {
|
||||
|
@ -43,7 +39,7 @@ export const BaseAccordion = ({
|
|||
<div key={i} {...propsGetter(true)}>
|
||||
<Component
|
||||
onClick={setActive}
|
||||
className="tw-w-full tw-bg-transparent tw-border-0 hover:tw-bg-secondary hover:tw-bg-opacity-20 hover:tw-cursor-pointer"
|
||||
className="tw:w-full tw:bg-transparent tw:border-0 tw:hover:bg-secondary/20 tw:hover:cursor-pointer"
|
||||
>
|
||||
{item[0]}
|
||||
</Component>
|
||||
|
|
|
@ -11,7 +11,7 @@ export const AsideViewMenuButton = ({
|
|||
}) => {
|
||||
const className = `w-full flex flex-row items-center px-4 py-2 ${extraClasses} ${
|
||||
active
|
||||
? 'font-bold lg:font-normal bg-secondary bg-opacity-10 lg:bg-secondary lg:text-secondary-content lg:bg-opacity-50'
|
||||
? 'font-bold lg:font-normal bg-secondary/10 lg:bg-secondary/50 lg:text-secondary-content'
|
||||
: 'lg:bg-neutral lg:text-neutral-content'
|
||||
}`
|
||||
const span = <span className="block grow text-left">{label}</span>
|
||||
|
|
|
@ -31,7 +31,7 @@ const flagIcons = {
|
|||
warning: WarningIcon,
|
||||
}
|
||||
|
||||
export const FlagTypeIcon = ({ type, className = 'tw-w-6 tw-h-6' }) => {
|
||||
export const FlagTypeIcon = ({ type, className = 'tw:w-6 tw:h-6' }) => {
|
||||
const Icon = flagIcons[type] || FixmeIcon
|
||||
|
||||
return <Icon className={className} />
|
||||
|
@ -39,14 +39,14 @@ export const FlagTypeIcon = ({ type, className = 'tw-w-6 tw-h-6' }) => {
|
|||
|
||||
export const Flag = ({ data, handleUpdate, strings }) => {
|
||||
const btnIcon = data.suggest?.icon ? (
|
||||
<FlagTypeIcon type={data.suggest.icon} className="tw-w-5 tw-h-6 sm:tw-w-6 tw-h-6" />
|
||||
<FlagTypeIcon type={data.suggest.icon} className="tw:w-5 tw:h-6 tw:sm:w-6 tw:h-6" />
|
||||
) : null
|
||||
|
||||
const button =
|
||||
data.suggest?.text && data.suggest?.update ? (
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline tw-flex tw-flex-row tw-items-center ${
|
||||
btnIcon ? 'tw-gap-6' : ''
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline tw:flex tw:flex-row tw:items-center ${
|
||||
btnIcon ? 'tw:gap-6' : ''
|
||||
}`}
|
||||
onClick={() => handleUpdate(data.suggest.update)}
|
||||
>
|
||||
|
@ -75,8 +75,8 @@ export const Flag = ({ data, handleUpdate, strings }) => {
|
|||
: null
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-col tw-gap-2 tw-items-start">
|
||||
<div className="first:tw-mt-0 tw-grow md flag tw-flex tw-flex-col tw-gap-2">
|
||||
<div className="tw:flex tw:flex-col tw:gap-2 tw:items-start">
|
||||
<div className="tw:first:mt-0 tw:grow md flag tw:flex tw:flex-col tw:gap-2">
|
||||
{desc ? (
|
||||
<MiniTip>
|
||||
<Markdown>{strings[desc] || desc}</Markdown>
|
||||
|
@ -89,7 +89,7 @@ export const Flag = ({ data, handleUpdate, strings }) => {
|
|||
) : null}
|
||||
</div>
|
||||
{button ? (
|
||||
<div className="tw-mt-2 tw-w-full tw-flex tw-flex-row tw-justify-end">{button}</div>
|
||||
<div className="tw:mt-2 tw:w-full tw:flex tw:flex-row tw:justify-end">{button}</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
|
@ -102,11 +102,11 @@ export const FlagsAccordionTitle = ({ flags }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<h5 className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-justify-between tw-w-full">
|
||||
<span className="tw-text-left">Flags ({Object.keys(flagList).length})</span>
|
||||
<FlagTypeIcon className="tw-w-8 tw-h-8" />
|
||||
<h5 className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:justify-between tw:w-full">
|
||||
<span className="tw:text-left">Flags ({Object.keys(flagList).length})</span>
|
||||
<FlagTypeIcon className="tw:w-8 tw:h-8" />
|
||||
</h5>
|
||||
<p className="tw-text-left">
|
||||
<p className="tw:text-left">
|
||||
{Object.keys(flagList).length > 1
|
||||
? 'Some issues about your current pattern need your attention.'
|
||||
: 'A specific issue about your current pattern needs your attention.'}
|
||||
|
@ -131,14 +131,14 @@ export const FlagsAccordionEntries = ({ flags, update, pattern, strings }) => {
|
|||
const title = flag.replace ? mustache.render(flag.title, flag.replace) : flag.title
|
||||
|
||||
return [
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-gap2 tw-justify-between" key={i}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<div className="tw-no-shrink">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:gap2 tw:justify-between" key={i}>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
<div className="tw:no-shrink">
|
||||
<FlagIcon type={flag.type} />
|
||||
</div>
|
||||
<span className="tw-font-medium tw-text-left">{strings[title] || title}</span>
|
||||
<span className="tw:font-medium tw:text-left">{strings[title] || title}</span>
|
||||
</div>
|
||||
<span className="tw-uppercase tw-font-bold">{flag.type}</span>
|
||||
<span className="tw:uppercase tw:font-bold">{flag.type}</span>
|
||||
</div>,
|
||||
<Flag key={key} data={flag} strings={strings} handleUpdate={handleUpdate} />,
|
||||
key,
|
||||
|
|
|
@ -61,7 +61,7 @@ export const HeaderMenuIcon = (props) => {
|
|||
// FIXME: Remove this when ready
|
||||
if (!headerMenuIcons[name]) console.log('FIXME: Add headerMenuIcon for ', name)
|
||||
|
||||
return <Icon {...props} className={`tw-h-5 tw-w-5 ${extraClasses}`} />
|
||||
return <Icon {...props} className={`tw:h-5 tw:w-5 ${extraClasses}`} />
|
||||
}
|
||||
|
||||
export const HeaderMenuDraftView = (props) => {
|
||||
|
@ -70,7 +70,7 @@ export const HeaderMenuDraftView = (props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-gap-0.5 lg:tw-gap-1">
|
||||
<div className="tw:flex tw:flex-row tw:gap-0.5 tw:lg:gap-1">
|
||||
<HeaderMenuDraftViewDesignOptions {...props} i18n={i18n} />
|
||||
<HeaderMenuDraftViewCoreSettings {...props} i18n={i18n} />
|
||||
<HeaderMenuDraftViewUiPreferences {...props} i18n={i18n} />
|
||||
|
@ -103,8 +103,8 @@ export const HeaderMenuTestViewDesignOptions = (props) => {
|
|||
tooltip="See how design options influence the pattern being generated."
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="options" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline">Test Options</span>
|
||||
<HeaderMenuIcon name="options" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline">Test Options</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -121,8 +121,8 @@ export const HeaderMenuTestViewDesignMeasurements = (props) => {
|
|||
tooltip="See how changes to a measurment influence the pattern being generated."
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="options" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline">Test Measurements</span>
|
||||
<HeaderMenuIcon name="options" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline">Test Measurements</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -145,7 +145,7 @@ export const HeaderMenuDropdown = (props) => {
|
|||
disabled
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
className={`tw-daisy-btn tw-daisy-btn-ghost hover:tw-bg-secondary hover:tw-bg-opacity-20 hover:tw-border-solid hover:tw-border-2 hover:tw-border-secondary tw-border tw-border-secondary tw-border-2 tw-border-dotted tw-daisy-btn-sm tw-px-2 tw-z-20 tw-relative`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-ghost tw:hover:bg-secondary/20 tw:hover:border-solid tw:hover:border-2 tw:hover:border-secondary tw:border tw:border-secondary tw:border-2 tw:border-dotted tw:daisy-btn-sm tw:px-2 tw:z-20 tw:relative`}
|
||||
>
|
||||
{toggle}
|
||||
</button>
|
||||
|
@ -153,26 +153,26 @@ export const HeaderMenuDropdown = (props) => {
|
|||
) : (
|
||||
<Tooltip tip={tooltip}>
|
||||
<div
|
||||
className={`tw-daisy-dropdown ${open === id ? 'tw-daisy-dropdown-open tw-z-20' : ''} ${end ? ' tw-daisy-dropdown-end' : ''}`}
|
||||
className={`tw:daisy-dropdown ${open === id ? 'tw:daisy-dropdown-open tw:z-20' : ''} ${end ? ' tw:daisy-dropdown-end' : ''}`}
|
||||
>
|
||||
<div
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
className="tw-daisy-btn tw-daisy-btn-ghost hover:tw-bg-secondary hover:tw-bg-opacity-20 tw-border-secondary/10 hover:tw-border-2 hover:tw-border-secondary tw-border tw-border-secondary tw-border-2 tw-border-solid tw-daisy-btn-sm tw-px-2 tw-z-20 tw-relative"
|
||||
className="tw:daisy-btn tw:daisy-btn-ghost tw:hover:bg-secondary/20 tw:border-secondary/10 tw:hover:border-2 tw:hover:border-secondary tw:border tw:border-secondary tw:border-2 tw:border-solid tw:daisy-btn-sm tw:px-2 tw:z-20 tw:relative"
|
||||
onClick={() => setOpen(open === id ? false : id)}
|
||||
>
|
||||
{toggle}
|
||||
</div>
|
||||
<div
|
||||
tabIndex={0}
|
||||
className="tw-daisy-dropdown-content tw-bg-base-100 tw-bg-opacity-90 tw-z-20 tw-shadow tw-left-0 !tw-fixed md:!tw-absolute tw-top-12 tw-w-screen md:tw-max-w-md tw-overflow-y-scroll tw-mb-12 tw-h-fit"
|
||||
className="tw:daisy-dropdown-content tw:bg-base-100/90 tw:z-20 tw:shadow tw:left-0 tw:fixed! tw:md:absolute! tw:top-12 tw:w-screen tw:md:max-w-md tw:overflow-y-scroll tw:mb-12 tw:h-fit"
|
||||
style={{ maxHeight: 'calc(100vh - 12rem)' }}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
{open === id && (
|
||||
<div
|
||||
className="tw-w-screen tw-h-screen tw-absolute tw-top-10 tw-left-0 tw-opacity-0"
|
||||
className="tw:w-screen tw:h-screen tw:absolute tw:top-10 tw:left-0 tw:opacity-0"
|
||||
style={{ width: '200vw', transform: 'translateX(-100vw)' }}
|
||||
onClick={() => setOpen(false)}
|
||||
></div>
|
||||
|
@ -189,8 +189,8 @@ export const HeaderMenuDraftViewDesignOptions = (props) => (
|
|||
tooltip="These options are specific to this design. You can use them to customize your pattern in a variety of ways."
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="options" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline tw-capitalize">
|
||||
<HeaderMenuIcon name="options" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline tw:capitalize">
|
||||
{props.state.design ? props.state.design : 'Design'} Options
|
||||
</span>
|
||||
</>
|
||||
|
@ -208,8 +208,8 @@ export const HeaderMenuDraftViewCoreSettings = (props) => {
|
|||
id="coreSettings"
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="settings" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline">Core Settings</span>
|
||||
<HeaderMenuIcon name="settings" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline">Core Settings</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -226,8 +226,8 @@ export const HeaderMenuDraftViewUiPreferences = (props) => {
|
|||
id="uiPreferences"
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="ui" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline">UI Preferences</span>
|
||||
<HeaderMenuIcon name="ui" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline">UI Preferences</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -246,8 +246,8 @@ export const HeaderMenuDraftViewFlags = (props) => {
|
|||
id="flags"
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="flag" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline">
|
||||
<HeaderMenuIcon name="flag" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline">
|
||||
Flags
|
||||
<span>({count})</span>
|
||||
</span>
|
||||
|
@ -262,8 +262,8 @@ export const HeaderMenuDraftViewFlags = (props) => {
|
|||
export const HeaderMenuDraftViewIcons = (props) => {
|
||||
const { update, state } = props
|
||||
const Button = HeaderMenuButton
|
||||
const size = 'tw-w-5 tw-h-5'
|
||||
const muted = 'tw-text-current tw-opacity-50'
|
||||
const size = 'tw:w-5 tw:h-5'
|
||||
const muted = 'tw:text-current tw:opacity-50'
|
||||
const ux = state.ui.ux
|
||||
const levels = {
|
||||
...props.config.uxLevels.core,
|
||||
|
@ -271,14 +271,14 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-hidden lg:tw-flex tw-flex-row tw-flex-wrap tw-items-center tw-justify-center tw-px-0.5 lg:tw-px-1">
|
||||
<div className="tw:hidden tw:lg:flex tw:flex-row tw:flex-wrap tw:items-center tw:justify-center tw:px-0.5 tw:lg:px-1">
|
||||
{ux >= levels.sa ? (
|
||||
<Button
|
||||
lgOnly
|
||||
updateHandler={update.toggleSa}
|
||||
tooltip="Turns Seam Allowance on or off (see Core Settings)"
|
||||
>
|
||||
<SaIcon className={`${size} ${state.settings.sabool ? 'tw-text-secondary' : muted}`} />
|
||||
<SaIcon className={`${size} ${state.settings.sabool ? 'tw:text-secondary' : muted}`} />
|
||||
</Button>
|
||||
) : null}
|
||||
{ux >= levels.units ? (
|
||||
|
@ -291,7 +291,7 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
>
|
||||
<UnitsIcon
|
||||
className={`${size} ${
|
||||
state.settings.units === 'imperial' ? 'tw-text-secondary' : muted
|
||||
state.settings.units === 'imperial' ? 'tw:text-secondary' : muted
|
||||
}`}
|
||||
/>
|
||||
</Button>
|
||||
|
@ -303,7 +303,7 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
tooltip="Turns Paperless on or off (see Core Settings)"
|
||||
>
|
||||
<PaperlessIcon
|
||||
className={`${size} ${state.settings.paperless ? 'tw-text-secondary' : muted}`}
|
||||
className={`${size} ${state.settings.paperless ? 'tw:text-secondary' : muted}`}
|
||||
/>
|
||||
</Button>
|
||||
) : null}
|
||||
|
@ -314,7 +314,7 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
tooltip="Turns Details on or off (see Core Settings)"
|
||||
>
|
||||
<DetailIcon
|
||||
className={`${size} ${!state.settings.complete ? 'tw-text-secondary' : muted}`}
|
||||
className={`${size} ${!state.settings.complete ? 'tw:text-secondary' : muted}`}
|
||||
/>
|
||||
</Button>
|
||||
) : null}
|
||||
|
@ -325,7 +325,7 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
tooltip="Turns Expand on or off (see Core Settings)"
|
||||
>
|
||||
<ExpandIcon
|
||||
className={`${size} ${state.settings.expand ? 'tw-text-secondary' : muted}`}
|
||||
className={`${size} ${state.settings.expand ? 'tw:text-secondary' : muted}`}
|
||||
/>
|
||||
</Button>
|
||||
) : null}
|
||||
|
@ -336,7 +336,7 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
updateHandler={() => update.ui('aside', state.ui.aside ? 0 : 1)}
|
||||
tooltip="Toggles the side menu (see UI Preferences)"
|
||||
>
|
||||
<AsideIcon className={`${size} ${state.ui.aside ? 'tw-text-secondary' : muted}`} />
|
||||
<AsideIcon className={`${size} ${state.ui.aside ? 'tw:text-secondary' : muted}`} />
|
||||
</Button>
|
||||
) : null}
|
||||
{ux >= levels.renderer ? (
|
||||
|
@ -348,7 +348,7 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
tooltip="Switches the Render Engine between React and SVG (see UI Preferences)"
|
||||
>
|
||||
<RocketIcon
|
||||
className={`${size} ${state.ui.renderer === 'svg' ? 'tw-text-secondary' : muted}`}
|
||||
className={`${size} ${state.ui.renderer === 'svg' ? 'tw:text-secondary' : muted}`}
|
||||
/>
|
||||
</Button>
|
||||
) : null}
|
||||
|
@ -359,18 +359,18 @@ export const HeaderMenuDraftViewIcons = (props) => {
|
|||
export const HeaderMenuUndoIcons = (props) => {
|
||||
const { update, state, Design } = props
|
||||
const Button = HeaderMenuButton
|
||||
const size = 'tw-w-5 tw-h-5'
|
||||
const size = 'tw:w-5 tw:h-5'
|
||||
const undos = state._?.undos && state._.undos.length > 0 ? state._.undos : false
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-items-center tw-justify-center tw-px-0.5 lg:tw-px-1">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:items-center tw:justify-center tw:px-0.5 tw:lg:px-1">
|
||||
<Button
|
||||
lgOnly
|
||||
updateHandler={() => update.restore(0, state._)}
|
||||
tooltip="Undo the most recent change"
|
||||
disabled={undos ? false : true}
|
||||
>
|
||||
<UndoIcon className={`${size} ${undos ? 'tw-text-secondary' : ''}`} text="1" />
|
||||
<UndoIcon className={`${size} ${undos ? 'tw:text-secondary' : ''}`} text="1" />
|
||||
</Button>
|
||||
<Button
|
||||
lgOnly
|
||||
|
@ -378,7 +378,7 @@ export const HeaderMenuUndoIcons = (props) => {
|
|||
tooltip="Undo all changes since the last save point"
|
||||
disabled={undos ? false : true}
|
||||
>
|
||||
<UndoIcon className={`${size} ${undos ? 'tw-text-secondary' : ''}`} text="A" />
|
||||
<UndoIcon className={`${size} ${undos ? 'tw:text-secondary' : ''}`} text="A" />
|
||||
</Button>
|
||||
<HeaderMenuDropdown
|
||||
end
|
||||
|
@ -388,13 +388,13 @@ export const HeaderMenuUndoIcons = (props) => {
|
|||
disabled={undos ? false : true}
|
||||
toggle={
|
||||
<>
|
||||
<UndoIcon className="tw-w-4 tw-h-4" stroke={3} />
|
||||
<span className="tw-hidden lg:tw-inline">Undo</span>
|
||||
<UndoIcon className="tw:w-4 tw:h-4" stroke={3} />
|
||||
<span className="tw:hidden tw:lg:inline">Undo</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{undos ? (
|
||||
<ul className="tw-daisy-dropdown-content tw-bg-base-100 tw-bg-opacity-90 tw-z-20 tw-shadow tw-left-0 !tw-fixed md:!tw-absolute tw-w-screen md:tw-w-96 tw-px-4 md:tw-p-2 md:tw-pt-0 tw-contents">
|
||||
<ul className="tw:daisy-dropdown-content tw:bg-base-100/90 tw:z-20 tw:shadow tw:left-0 tw:fixed! tw:md:absolute! tw:w-screen tw:md:w-96 tw:px-4 tw:md:p-2 tw:md:pt-0 tw:contents">
|
||||
{undos.slice(0, 9).map((step, index) => (
|
||||
<li key={index}>
|
||||
<UndoStep {...{ step, update, state, Design, index }} compact />
|
||||
|
@ -402,9 +402,9 @@ export const HeaderMenuUndoIcons = (props) => {
|
|||
))}
|
||||
<li key="view">
|
||||
<ButtonFrame dense onClick={() => update.view('undos')}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-align-center tw-justify-between tw-gap-2 tw-w-full">
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-align-start tw-gap-2 tw-grow">
|
||||
<UndoIcon className="tw-w-5 tw-h-5 tw-text-secondary" />
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:align-center tw:justify-between tw:gap-2 tw:w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:align-start tw:gap-2 tw:grow">
|
||||
<UndoIcon className="tw:w-5 tw:h-5 tw:text-secondary" />
|
||||
{viewLabels.undos.t}
|
||||
</div>
|
||||
{undos.length}
|
||||
|
@ -418,10 +418,10 @@ export const HeaderMenuUndoIcons = (props) => {
|
|||
updateHandler={update.clearPattern}
|
||||
tooltip="Reset all settings, but keep the design and measurements"
|
||||
>
|
||||
<TrashIcon className={`${size} tw-text-secondary`} />
|
||||
<TrashIcon className={`${size} tw:text-secondary`} />
|
||||
</Button>
|
||||
<Button updateHandler={update.clearAll} tooltip="Reset the editor completely">
|
||||
<ResetAllIcon className={`${size} tw-text-secondary`} />
|
||||
<ResetAllIcon className={`${size} tw:text-secondary`} />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
@ -430,11 +430,11 @@ export const HeaderMenuUndoIcons = (props) => {
|
|||
export const HeaderMenuTestIcons = (props) => {
|
||||
const { update, state, Design } = props
|
||||
const Button = HeaderMenuButton
|
||||
const size = 'tw-w-5 tw-h-5'
|
||||
const size = 'tw:w-5 tw:h-5'
|
||||
const undos = state._?.undos && state._.undos.length > 0 ? state._.undos : false
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-items-center tw-justify-center tw-px-0.5 lg:tw-px-1">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:items-center tw:justify-center tw:px-0.5 tw:lg:px-1">
|
||||
<Button
|
||||
updateHandler={() => update.settings('sample', undefined)}
|
||||
tooltip="Clear the test so you can select another"
|
||||
|
@ -449,7 +449,7 @@ export const HeaderMenuSaveIcons = (props) => {
|
|||
const { update, state } = props
|
||||
const backend = useBackend()
|
||||
const Button = HeaderMenuButton
|
||||
const size = 'tw-w-5 tw-h-5'
|
||||
const size = 'tw:w-5 tw:h-5'
|
||||
const saveable = state._?.undos && state._.undos.length > 0
|
||||
|
||||
/*
|
||||
|
@ -473,22 +473,22 @@ export const HeaderMenuSaveIcons = (props) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-items-center tw-justify-center tw-px-2">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:items-center tw:justify-center tw:px-2">
|
||||
<Button updateHandler={savePattern} tooltip="Save pattern" disabled={saveable ? false : true}>
|
||||
<SaveIcon className={`${size} ${saveable ? 'tw-text-success' : ''}`} />
|
||||
<SaveIcon className={`${size} ${saveable ? 'tw:text-success' : ''}`} />
|
||||
</Button>
|
||||
<Button updateHandler={() => update.view('save')} tooltip="Save pattern as...">
|
||||
<SaveAsIcon className={`${size} tw-text-secondary`} />
|
||||
<SaveAsIcon className={`${size} tw:text-secondary`} />
|
||||
</Button>
|
||||
<Button updateHandler={() => update.view('export')} tooltip="Export pattern">
|
||||
<ExportIcon className={`${size} tw-text-secondary`} />
|
||||
<ExportIcon className={`${size} tw:text-secondary`} />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const HeaderMenuIconSpacer = () => (
|
||||
<span className="tw-hidden lg:tw-inline tw-px-1 tw-font-bold tw-opacity-30">|</span>
|
||||
<span className="tw:hidden tw:lg:inline tw:px-1 tw:font-bold tw:opacity-30">|</span>
|
||||
)
|
||||
|
||||
export const HeaderMenuButton = ({
|
||||
|
@ -500,7 +500,7 @@ export const HeaderMenuButton = ({
|
|||
}) => (
|
||||
<Tooltip tip={tooltip}>
|
||||
<button
|
||||
className={`${lgOnly ? 'tw-hidden lg:tw-inline' : ''} tw-daisy-btn tw-daisy-btn-ghost tw-daisy-btn-sm tw-px-1 disabled:tw-bg-transparent`}
|
||||
className={`${lgOnly ? 'tw:hidden tw:lg:inline' : ''} tw:daisy-btn tw:daisy-btn-ghost tw:daisy-btn-sm tw:px-1 tw:disabled:bg-transparent`}
|
||||
onClick={updateHandler}
|
||||
disabled={disabled}
|
||||
>
|
||||
|
@ -533,19 +533,17 @@ export const HeaderMenuViewMenu = (props) => {
|
|||
output.push(
|
||||
<li
|
||||
key={i}
|
||||
className="tw-mb-1 tw-flex tw-flex-row tw-items-center tw-justify-between tw-w-full"
|
||||
className="tw:mb-1 tw:flex tw:flex-row tw:items-center tw:justify-between tw:w-full"
|
||||
>
|
||||
<a
|
||||
className={`tw-w-full tw-text-base-content
|
||||
tw-flex tw-flex-row tw-items-center tw-gap-2 md:tw-gap-4 tw-p-2 tw-px-4
|
||||
hover:tw-cursor-pointer hover:tw-text-base-content
|
||||
hover:tw-bg-secondary hover:tw-bg-opacity-20 ${
|
||||
viewName === state.view ? 'tw-bg-secondary tw-bg-opacity-20' : ''
|
||||
}`}
|
||||
className={`tw:w-full tw:text-base-content
|
||||
tw:flex tw:flex-row tw:items-center tw:gap-2 tw:md:gap-4 tw:p-2 tw:px-4
|
||||
tw:hover:cursor-pointer tw:hover:text-base-content
|
||||
tw:hover:bg-secondary/20 ${viewName === state.view ? 'tw:bg-secondary/20' : ''}`}
|
||||
onClick={() => update.view(viewName)}
|
||||
>
|
||||
<ViewIcon view={viewName} className="tw-w-6 tw-h-6 tw-grow-0" />
|
||||
<span className="tw-text-left tw-grow tw-font-medium">
|
||||
<ViewIcon view={viewName} className="tw:w-6 tw:h-6 tw:grow-0" />
|
||||
<span className="tw:text-left tw:grow tw:font-medium">
|
||||
{viewLabels[viewName]?.t || viewName}
|
||||
</span>
|
||||
</a>
|
||||
|
@ -561,8 +559,8 @@ export const HeaderMenuViewMenu = (props) => {
|
|||
id="views"
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="right" stroke={3} extraClasses="tw-text-secondary tw-rotate-90" />
|
||||
<span className="tw-hidden lg:tw-inline">
|
||||
<HeaderMenuIcon name="right" stroke={3} extraClasses="tw:text-secondary tw:rotate-90" />
|
||||
<span className="tw:hidden tw:lg:inline">
|
||||
{viewLabels[state.view] ? viewLabels[state.view].t : 'Views'}
|
||||
</span>
|
||||
</>
|
||||
|
@ -570,7 +568,7 @@ export const HeaderMenuViewMenu = (props) => {
|
|||
>
|
||||
<ul
|
||||
tabIndex={i}
|
||||
className="tw-daisy-dropdown-content tw-bg-base-100 tw-bg-opacity-95 tw-z-20 tw-shadow tw-left-0 !tw-fixed md:!tw-absolute tw-w-screen md:tw-max-w-lg md:tw-pt-0 tw-mt-14 md:tw-mt-0 tw-contents"
|
||||
className="tw:daisy-dropdown-content tw:bg-base-100/95tw:z-20 tw:shadow tw:left-0 tw:fixed! tw:md:absolute! tw:w-screen tw:md:max-w-lg tw:md:pt-0 tw:mt-14 tw:md:mt-0 tw:contents"
|
||||
>
|
||||
{output}
|
||||
</ul>
|
||||
|
@ -586,8 +584,8 @@ export const HeaderMenuLayoutView = (props) => (
|
|||
tooltip="These options are specific to this design. You can use them to customize your pattern in a variety of ways."
|
||||
toggle={
|
||||
<>
|
||||
<HeaderMenuIcon name="layout" extraClasses="tw-text-secondary" />
|
||||
<span className="tw-hidden lg:tw-inline">Print Settings</span>
|
||||
<HeaderMenuIcon name="layout" extraClasses="tw:text-secondary" />
|
||||
<span className="tw:hidden tw:lg:inline">Print Settings</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
@ -642,10 +640,10 @@ export const HeaderMenuLayoutViewIcons = (props) => {
|
|||
return (
|
||||
<>
|
||||
<Tooltip tip="Number of pages required for the current layout">
|
||||
<span className="tw-px-1 tw-font-bold tw-text-sm tw-block tw-h-8 tw-py-1 tw-opacity-80">
|
||||
<span className="tw:px-1 tw:font-bold tw:text-sm tw:block tw:h-8 tw:py-1 tw:opacity-80">
|
||||
<span className="">
|
||||
{count} pages
|
||||
<span className="tw-pl-1 tw-text-xs tw-font-medium">
|
||||
<span className="tw:pl-1 tw:text-xs tw:font-medium">
|
||||
({cols}x{rows}, {blank} blank)
|
||||
</span>
|
||||
</span>
|
||||
|
@ -653,7 +651,7 @@ export const HeaderMenuLayoutViewIcons = (props) => {
|
|||
</Tooltip>
|
||||
<Tooltip tip="Apply this layout to the pattern">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-ghost tw-daisy-btn-sm tw-px-1 disabled:tw-bg-transparent tw-text-secondary"
|
||||
className="tw:daisy-btn tw:daisy-btn-ghost tw:daisy-btn-sm tw:px-1 tw:disabled:bg-transparent tw:text-secondary"
|
||||
onClick={applyLayout}
|
||||
disabled={!layoutValid}
|
||||
>
|
||||
|
@ -662,7 +660,7 @@ export const HeaderMenuLayoutViewIcons = (props) => {
|
|||
</Tooltip>
|
||||
<Tooltip tip="Generate a PDF that you can print">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-ghost tw-daisy-btn-sm tw-px-1 disabled:tw-bg-transparent tw-text-secondary"
|
||||
className="tw:daisy-btn tw:daisy-btn-ghost tw:daisy-btn-sm tw:px-1 tw:disabled:bg-transparent tw:text-secondary"
|
||||
onClick={() => update.view('export')}
|
||||
>
|
||||
<PrintIcon />
|
||||
|
@ -670,7 +668,7 @@ export const HeaderMenuLayoutViewIcons = (props) => {
|
|||
</Tooltip>
|
||||
<Tooltip tip="Reset the custom layout">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-ghost tw-daisy-btn-sm tw-px-1 disabled:tw-bg-transparent tw-text-secondary"
|
||||
className="tw:daisy-btn tw:daisy-btn-ghost tw:daisy-btn-sm tw:px-1 tw:disabled:bg-transparent tw:text-secondary"
|
||||
onClick={resetLayout}
|
||||
>
|
||||
<ResetIcon />
|
||||
|
@ -705,12 +703,12 @@ export const HeaderMenu = ({ config, Design, pattern, state, update, strings })
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`tw-flex tw-sticky tw-top-0 ${
|
||||
state.ui.kiosk ? 'tw-z-50' : 'tw-z-20'
|
||||
} tw-transition-[top] tw-duration-300 tw-ease-in-out`}
|
||||
className={`tw:flex tw:sticky tw:top-0 ${
|
||||
state.ui.kiosk ? 'tw:z-50' : 'tw:z-20'
|
||||
} tw:transition-[top] tw:duration-300 tw:ease-in-out`}
|
||||
>
|
||||
<div
|
||||
className={`tw-flex tw-flex-row tw-flex-wrap tw-gap-0.5 lg:tw-gap-1 tw-w-full tw-items-start tw-justify-center tw-py-1 md:tw-py-1.5`}
|
||||
className={`tw:flex tw:flex-row tw:flex-wrap tw:gap-0.5 tw:lg:gap-1 tw:w-full tw:items-start tw:justify-center tw:py-1 tw:md:py-1.5`}
|
||||
>
|
||||
<HeaderMenuViewMenu {...{ config, state, update, open, setOpen, strings }} />
|
||||
<ViewSpecificMenu {...{ config, state, update, Design, pattern, open, setOpen, strings }} />
|
||||
|
|
|
@ -36,13 +36,13 @@ export const LoadingStatus = ({ state, update }) => {
|
|||
if (!state._.loading || Object.keys(state._.loading).length < 1) return null
|
||||
|
||||
const colorClasses = {
|
||||
info: 'tw-bg-info tw-text-info-content',
|
||||
primary: 'tw-bg-primary tw-text-primary-content',
|
||||
info: 'tw:bg-info tw:text-info-content',
|
||||
primary: 'tw:bg-primary tw:text-primary-content',
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tw-fixed tw-bottom-4 md:tw-buttom-28 tw-left-0 tw-w-full tw-z-30 md:tw-px-4 md:tw-mx-auto mb-4">
|
||||
<div className="tw-flex tw-flex-col tw-gap-2">
|
||||
<div className="tw:fixed tw:bottom-4 md:tw:buttom-28 tw:left-0 tw:w-full tw:z-30 tw:md:px-4 tw:md:mx-auto mb-4">
|
||||
<div className="tw:flex tw:flex-col tw:gap-2">
|
||||
{Object.entries(state._.loading).map(([id, custom]) => {
|
||||
const conf = {
|
||||
...config.defaults,
|
||||
|
@ -52,20 +52,20 @@ export const LoadingStatus = ({ state, update }) => {
|
|||
return (
|
||||
<div
|
||||
key={id}
|
||||
className={`tw-w-full md:tw-max-w-2xl tw-m-auto tw-bg-${
|
||||
className={`tw:w-full tw:md:max-w-2xl tw:m-auto tw:bg-${
|
||||
conf.color
|
||||
} tw-text-${conf.color}-content tw-flex tw-flex-row tw-items-center tw-gap-4 tw-p-4 tw-px-4 ${
|
||||
conf.fading ? 'tw-opacity-0' : 'tw-opacity-100'
|
||||
} tw:text-${conf.color}-content tw:flex tw:flex-row tw:items-center tw:gap-4 tw:p-4 tw:px-4 ${
|
||||
conf.fading ? 'tw:opacity-0' : 'tw:opacity-100'
|
||||
}
|
||||
tw-transition-opacity tw-delay-[${config.timeout * 1000 - 400}ms] tw-duration-300
|
||||
md:tw-rounded-lg tw-shadow tw-text-secondary-content tw-text-lg lg:tw-text-xl tw-font-medium md:tw-bg-opacity-90
|
||||
${conf.color === 'info' ? 'tw-text-neutral' : ''}
|
||||
tw:transition-opacity tw:delay-[${config.timeout * 1000 - 400}ms] tw:duration-300
|
||||
tw:md:rounded-lg tw:shadow tw:text-secondary-content tw:text-lg tw:lg:text-xl tw:font-medium
|
||||
${conf.color === 'info' ? 'tw:text-neutral' : ''}
|
||||
`}
|
||||
>
|
||||
<span className={`tw-shrink-0 tw-text-${conf.color}-content`}>
|
||||
<span className={`tw:shrink-0 tw:text-${conf.color}-content`}>
|
||||
<Icon />
|
||||
</span>
|
||||
<div className={conf.color === 'info' ? 'tw-text-neutral tw-w-full' : 'tw-w-full'}>
|
||||
<div className={conf.color === 'info' ? 'tw:text-neutral tw:w-full' : 'tw:w-full'}>
|
||||
{conf.msg}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,7 @@ export const MeasurementsEditor = ({ Design, update, state, helpProvider = false
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-max-w-2xl tw-mx-auto">
|
||||
<div className="tw:max-w-2xl tw:mx-auto">
|
||||
<h4>Required Measurements</h4>
|
||||
{Object.keys(Design.patternConfig.measurements).length === 0 ? (
|
||||
<p>This design does not require any measurements.</p>
|
||||
|
|
|
@ -407,8 +407,8 @@ const Button = ({ onClickCb, transform, Icon, children, title = '' }) => {
|
|||
<g transform={transform} className="svg-layout-button group">
|
||||
<title>{title}</title>
|
||||
<rect width={rectSize} height={rectSize} className="button" rx="2" ry="2" />
|
||||
<Icon className="group-hover:tw-text-primary-content" />
|
||||
<rect width={rectSize} height={rectSize} onClick={_onClick} className="tw-fill-transparent" />
|
||||
<Icon className="tw:group-hover:text-primary-content" />
|
||||
<rect width={rectSize} height={rectSize} onClick={_onClick} className="tw:fill-transparent" />
|
||||
</g>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -30,20 +30,20 @@ export const PatternLayout = (props) => {
|
|||
|
||||
return (
|
||||
<ZoomContextProvider>
|
||||
<div className="tw-flex tw-flex-col tw-h-full">
|
||||
<div className="tw:flex tw:flex-col tw:h-full">
|
||||
<HeaderMenu
|
||||
state={props.state}
|
||||
{...{ update, Design, pattern, config, strings: props.strings }}
|
||||
/>
|
||||
<div className="tw-flex lg:tw-flex-row tw-grow lg:tw-max-h-[90vh] tw-max-h-[calc(100vh-3rem)] tw-h-full tw-py-2 lg:tw-mt-2">
|
||||
<div className="lg:tw-w-2/3 tw-flex tw-flex-col tw-h-full tw-grow tw-p-2 tw-shadow tw-mx-2">
|
||||
<div className="tw:flex tw:lg:flex-row tw:grow tw:lg:max-h-[90vh] tw:max-h-[calc(100vh-3rem)] tw:h-full tw:py-2 tw:lg:mt-2">
|
||||
<div className="tw:lg:w-2/3 tw:flex tw:flex-col tw:h-full tw:grow tw:p-2 tw:shadow tw:mx-2">
|
||||
{props.output}
|
||||
</div>
|
||||
{state.ui?.aside ? (
|
||||
<div
|
||||
className={`tw-hidden xl:tw-block tw-w-1/3 tw-shrink tw-grow-0 lg:tw-p-4 tw-max-w-2xl tw-h-full tw-overflow-scroll`}
|
||||
className={`tw:hidden tw:xl:block tw:w-1/3 tw:shrink tw:grow-0 tw:lg:p-4 tw:max-w-2xl tw:h-full tw:overflow-scroll`}
|
||||
>
|
||||
<h5 className="tw-capitalize">{pattern.designConfig.data.id} Options</h5>
|
||||
<h5 className="tw:capitalize">{pattern.designConfig.data.id} Options</h5>
|
||||
<DesignOptionsMenu {...props} />
|
||||
<h5>Core Settings</h5>
|
||||
<CoreSettingsMenu {...props} />
|
||||
|
|
|
@ -46,7 +46,7 @@ export const UserSetPicker = ({
|
|||
|
||||
if (!hasSets)
|
||||
return (
|
||||
<div className="tw-w-full tw-max-w-3xl tw-mx-auto">
|
||||
<div className="tw:w-full tw:max-w-3xl tw:mx-auto">
|
||||
<Popout tip>
|
||||
<h5> You do not (yet) have any of your own measurements sets</h5>
|
||||
<p>
|
||||
|
@ -56,14 +56,14 @@ export const UserSetPicker = ({
|
|||
{config.hrefNewSet ? (
|
||||
<a
|
||||
href={config.hrefNewSet}
|
||||
className="tw-daisy-btn tw-daisy-btn-accent tw-capitalize"
|
||||
className="tw:daisy-btn tw:daisy-btn-accent tw:capitalize"
|
||||
target="_BLANK"
|
||||
rel="nofollow"
|
||||
>
|
||||
Create a new measurements set
|
||||
</a>
|
||||
) : null}
|
||||
<p className="tw-text-sm">
|
||||
<p className="tw:text-sm">
|
||||
Because our patterns are bespoke, we strongly suggest you take accurate measurements.
|
||||
</p>
|
||||
</Popout>
|
||||
|
@ -73,7 +73,7 @@ export const UserSetPicker = ({
|
|||
return (
|
||||
<>
|
||||
{okSets.length > 0 && (
|
||||
<div className="tw-grid tw-grid-cols-2 md:tw-grid-cols-4 lg:tw-grid-cols-6 tw-gap-2 tw-mt-4">
|
||||
<div className="tw:grid tw:grid-cols-2 tw:md:grid-cols-4 tw:lg:grid-cols-6 tw:gap-2 tw:mt-4">
|
||||
{okSets.map((set) => (
|
||||
<MsetCard
|
||||
href={false}
|
||||
|
@ -87,13 +87,13 @@ export const UserSetPicker = ({
|
|||
</div>
|
||||
)}
|
||||
{lackingSets.length > 0 ? (
|
||||
<div className="tw-my-4">
|
||||
<div className="tw:my-4">
|
||||
<Popout note>
|
||||
<h5>
|
||||
Some of your measurements sets lack the measurements required to generate this pattern
|
||||
</h5>
|
||||
</Popout>
|
||||
<div className="tw-grid tw-grid-cols-2 md:tw-grid-cols-4 lg:tw-grid-cols-6 tw-gap-2">
|
||||
<div className="tw:grid tw:grid-cols-2 tw:md:grid-cols-4 tw:lg:grid-cols-6 tw:gap-2">
|
||||
{lackingSets.map((set) => (
|
||||
<MsetCard
|
||||
{...{ set, Design }}
|
||||
|
@ -154,7 +154,7 @@ export const BookmarkedSetPicker = ({
|
|||
return (
|
||||
<>
|
||||
{okSets.length > 0 && (
|
||||
<div className="tw-grid tw-grid-cols-2 md:tw-grid-cols-4 lg:tw-grid-cols-6 tw-gap-2">
|
||||
<div className="tw:grid tw:grid-cols-2 tw:md:grid-cols-4 tw:lg:grid-cols-6 tw:gap-2">
|
||||
{okSets.map((set) => (
|
||||
<MsetCard
|
||||
href={false}
|
||||
|
@ -168,14 +168,14 @@ export const BookmarkedSetPicker = ({
|
|||
</div>
|
||||
)}
|
||||
{lackingSets.length > 0 && (
|
||||
<div className="tw-my-4">
|
||||
<div className="tw:my-4">
|
||||
<Popout note>
|
||||
<h5>
|
||||
Some of these measurements sets lack the measurements required to generate this
|
||||
pattern
|
||||
</h5>
|
||||
</Popout>
|
||||
<div className="tw-grid tw-grid-cols-2 md:tw-grid-cols-4 lg:tw-grid-cols-6 tw-gap-2">
|
||||
<div className="tw:grid tw:grid-cols-2 tw:md:grid-cols-4 tw:lg:grid-cols-6 tw:gap-2">
|
||||
{lackingSets.map((set) => (
|
||||
<MsetCard
|
||||
href={false}
|
||||
|
@ -216,7 +216,7 @@ export const CuratedSetPicker = ({ clickHandler }) => {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className="tw-max-w-7xl">
|
||||
<div className="tw:max-w-7xl">
|
||||
<CuratedMeasurementsSetLineup
|
||||
clickHandler={clickHandler}
|
||||
sets={orderBy(sets, 'height', 'asc')}
|
||||
|
@ -227,9 +227,9 @@ export const CuratedSetPicker = ({ clickHandler }) => {
|
|||
|
||||
export const CuratedMeasurementsSetLineup = ({ sets = [], clickHandler }) => (
|
||||
<div
|
||||
className={`tw-w-full tw-flex tw-flex-row ${
|
||||
sets.length > 1 ? 'tw-justify-start tw-px-8' : 'tw-justify-center'
|
||||
} tw-overflow-x-scroll`}
|
||||
className={`tw:w-full tw:flex tw:flex-row ${
|
||||
sets.length > 1 ? 'tw:justify-start tw:px-8' : 'tw:justify-center'
|
||||
} tw:overflow-x-scroll`}
|
||||
style={{
|
||||
backgroundImage: `url(/img/lineup-backdrop.svg)`,
|
||||
width: 'auto',
|
||||
|
@ -240,7 +240,7 @@ export const CuratedMeasurementsSetLineup = ({ sets = [], clickHandler }) => (
|
|||
{sets.map((set) => {
|
||||
const props = {
|
||||
className:
|
||||
'tw-aspect-[1/3] tw-w-auto tw-h-96 tw-bg-transparent tw-border-0 hover:tw-cursor-pointer hover:tw-bg-secondary/20',
|
||||
'tw:aspect-1/3 tw:w-auto tw:h-96 tw:bg-transparent tw:border-0 tw:hover:cursor-pointer tw:hover:bg-secondary/20',
|
||||
style: {
|
||||
backgroundImage: `url(${cloudflareImageUrl({
|
||||
id: `cset-${set.id}`,
|
||||
|
@ -255,7 +255,7 @@ export const CuratedMeasurementsSetLineup = ({ sets = [], clickHandler }) => (
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-col tw-items-center" key={set.id}>
|
||||
<div className="tw:flex tw:flex-col tw:items-center" key={set.id}>
|
||||
<button {...props} key={set.id}></button>
|
||||
<b>{set.nameEn}</b>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@ export const Tooltip = (props) => {
|
|||
return (
|
||||
<div
|
||||
{...rest}
|
||||
className={`tw-daisy-tooltip tw-daisy-tooltip-bottom before:tw-bg-base-200 before:tw-shadow before:tw-text-base-content`}
|
||||
className={`tw:daisy-tooltip tw:daisy-tooltip-bottom tw:before:bg-base-200 tw:before:shadow tw:before:text-base-content`}
|
||||
data-tip={tip}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -11,24 +11,24 @@ export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref
|
|||
const { onTransformed, zoomFunctions, setZoomFunctions } = useContext(ZoomContext)
|
||||
|
||||
return (
|
||||
<div className="tw-relative">
|
||||
<div className="tw-absolute tw-top-0 tw-right-0 tw-z-20">
|
||||
<div className="tw-flex tw-flex-row tw-gap-1 tw-items-center">
|
||||
<div className="tw:relative">
|
||||
<div className="tw:absolute tw:top-0 tw:right-0 tw:z-20">
|
||||
<div className="tw:flex tw:flex-row tw:gap-1 tw:items-center">
|
||||
<button
|
||||
onClick={() => props.update.ui('rotate', rotate ? 0 : 1)}
|
||||
className="hover:tw-text-secondary"
|
||||
className="tw:hover:text-secondary"
|
||||
>
|
||||
<RotateIcon className={`tw-h-6 tw-w-6 ${rotate ? 'tw-text-success' : ''}`} />
|
||||
<RotateIcon className={`tw:h-6 tw:w-6 ${rotate ? 'tw:text-success' : ''}`} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => (zoomFunctions.zoomIn ? zoomFunctions.zoomIn() : null)}
|
||||
className="hover:tw-text-secondary"
|
||||
className="tw:hover:text-secondary"
|
||||
>
|
||||
<ZoomInIcon />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => (zoomFunctions.zoomOut ? zoomFunctions.zoomOut() : null)}
|
||||
className="hover:tw-text-secondary"
|
||||
className="tw:hover:text-secondary"
|
||||
>
|
||||
<ZoomOutIcon />
|
||||
</button>
|
||||
|
@ -53,7 +53,7 @@ export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref
|
|||
<Pattern
|
||||
{...{ renderProps, components, strings }}
|
||||
ref={ref}
|
||||
className={`freesewing pattern tw-w-full ${rotate ? 'tw--rotate-90' : ''}`}
|
||||
className={`freesewing pattern tw:w-full ${rotate ? 'tw:-rotate-90' : ''}`}
|
||||
/>
|
||||
)}
|
||||
</TransformComponent>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { FormControl } from '@freesewing/react/components/Input'
|
|||
import { MiniTip } from '@freesewing/react/components/Mini'
|
||||
|
||||
/** @type {String} class to apply to buttons on open menu items */
|
||||
const iconButtonClass = 'tw-daisy-btn tw-daisy-btn-xs tw-daisy-btn-ghost tw-px-0 tw-text-accent'
|
||||
const iconButtonClass = 'tw:daisy-btn tw:daisy-btn-xs tw:daisy-btn-ghost tw:px-0 tw:text-accent'
|
||||
|
||||
/**
|
||||
* A generic component for handling a menu item.
|
||||
|
@ -81,15 +81,15 @@ export const MenuItem = ({
|
|||
}}
|
||||
>
|
||||
<EditIcon
|
||||
className={`tw-w-6 tw-h-6 ${
|
||||
override ? 'tw-bg-secondary tw-text-secondary-content tw-rounded' : 'tw-text-secondary'
|
||||
className={`tw:w-6 tw:h-6 ${
|
||||
override ? 'tw:bg-secondary tw:text-secondary-content tw:rounded' : 'tw:text-secondary'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
)
|
||||
const ResetButton = ({ disabled = false }) => (
|
||||
<button
|
||||
className={`${iconButtonClass} disabled:tw-bg-opacity-0`}
|
||||
className={iconButtonClass}
|
||||
disabled={disabled}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation()
|
||||
|
@ -107,10 +107,10 @@ export const MenuItem = ({
|
|||
<FormControl
|
||||
label={false}
|
||||
id={config.name}
|
||||
labelBR={<div className="tw-flex tw-flex-row tw-items-center tw-gap-2">{buttons}</div>}
|
||||
labelBR={<div className="tw:flex tw:flex-row tw:items-center tw:gap-2">{buttons}</div>}
|
||||
labelBL={
|
||||
<span
|
||||
className={`tw-text-base tw-font-medium tw--mt-2 tw-block ${changed ? 'tw-text-accent' : 'tw-opacity-50'}`}
|
||||
className={`tw:text-base tw:font-medium tw:-mt-2 tw:block ${changed ? 'tw:text-accent' : 'tw:opacity-50'}`}
|
||||
>
|
||||
{changed ? 'This is a custom value' : 'This is the default value'}
|
||||
</span>
|
||||
|
@ -190,9 +190,9 @@ export const MenuItemGroup = ({
|
|||
: () => <span role="img">fixme-icon</span>
|
||||
const Value = item.isGroup
|
||||
? () => (
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:font-medium">
|
||||
{Object.keys(item).filter((i) => i !== 'isGroup').length}
|
||||
<OptionsIcon className="tw-w-5 tw-h-5" />
|
||||
<OptionsIcon className="tw:w-5 tw:h-5" />
|
||||
</div>
|
||||
)
|
||||
: isDesignOptionsGroup
|
||||
|
@ -202,14 +202,14 @@ export const MenuItemGroup = ({
|
|||
: () => <span>¯\_(ツ)_/¯</span>
|
||||
|
||||
return [
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-w-full" key="a">
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-4 tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-between tw:w-full" key="a">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-4 tw:w-full">
|
||||
<ItemIcon />
|
||||
<span className="tw-font-medium tw-capitalize">
|
||||
<span className="tw:font-medium tw:capitalize">
|
||||
{item.title ? item.title : getItemLabel(i18n, itemName)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tw-font-bold">
|
||||
<div className="tw:font-bold">
|
||||
<Value
|
||||
current={currentValues[itemName]}
|
||||
config={item}
|
||||
|
@ -275,13 +275,13 @@ export const MenuItemGroup = ({
|
|||
*/
|
||||
export const MenuItemTitle = ({ name, current = null, open = false, emoji = '', Icon = false }) => (
|
||||
<div
|
||||
className={`tw-flex tw-flex-row tw-gap-1 tw-items-center tw-w-full ${open ? '' : 'tw-justify-between'}`}
|
||||
className={`tw:flex tw:flex-row tw:gap-1 tw:items-center tw:w-full ${open ? '' : 'tw:justify-between'}`}
|
||||
>
|
||||
<span className="tw-font-medium tw-capitalize tw-flex tw-flex-row tw-gap-2">
|
||||
<span className="tw:font-medium tw:capitalize tw:flex tw:flex-row tw:gap-2">
|
||||
{Icon ? <Icon /> : <span role="img">{emoji}</span>}
|
||||
fixme: {name}
|
||||
</span>
|
||||
<span className="tw-font-bold">{current}</span>
|
||||
<span className="tw:font-bold">{current}</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
|
@ -318,25 +318,25 @@ export const MenuButtonGroup = ({ structure, Button = false, Design, Icon, i18n
|
|||
: () => <span role="img">fixme-icon</span>
|
||||
const Value = item.isGroup
|
||||
? () => (
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-font-medium">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:font-medium">
|
||||
{Object.keys(item).filter((i) => i !== 'isGroup').length}
|
||||
<OptionsIcon className="tw-w-5 tw-h-5" />
|
||||
<OptionsIcon className="tw:w-5 tw:h-5" />
|
||||
</div>
|
||||
)
|
||||
: null
|
||||
|
||||
content.push([
|
||||
<div
|
||||
className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-w-full tw-pl-0 tw-pr-4 tw-py-2"
|
||||
className="tw:flex tw:flex-row tw:items-center tw:justify-between tw:w-full tw:pl-0 tw:pr-4 tw:py-2"
|
||||
key="a"
|
||||
>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-4 tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-4 tw:w-full">
|
||||
<ItemIcon />
|
||||
<span className="tw-font-medium tw-capitalize">
|
||||
<span className="tw:font-medium tw:capitalize">
|
||||
{item.title ? item.title : getItemLabel(i18n, itemName)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tw-font-bold">
|
||||
<div className="tw:font-bold">
|
||||
<Value config={item} Design={Design} />
|
||||
</div>
|
||||
</div>,
|
||||
|
@ -355,7 +355,7 @@ export const MenuButtonGroup = ({ structure, Button = false, Design, Icon, i18n
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-col tw-gap-0.5 tw-ml-4">
|
||||
<div className="tw:flex tw:flex-col tw:gap-0.5 tw:ml-4">
|
||||
{content.filter((item) => item !== null)}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -13,19 +13,19 @@ export const DraftMenu = ({ Design, pattern, state, update, i18n }) => {
|
|||
{
|
||||
t: 'Design Options',
|
||||
d: 'These options are specific to this design. You can use them to customize your pattern in a variety of ways.',
|
||||
icon: <OptionsIcon className="tw-w-8 tw-h-8" />,
|
||||
icon: <OptionsIcon className="tw:w-8 tw:h-8" />,
|
||||
menu: <DesignOptionsMenu {...menuProps} />,
|
||||
},
|
||||
{
|
||||
t: 'Core Settings',
|
||||
d: 'These settings are not specific to the design, but instead allow you to customize various parameters of the FreeSewing core library, which generates the design for you.',
|
||||
icon: <SettingsIcon className="tw-w-8 tw-h-8" />,
|
||||
icon: <SettingsIcon className="tw:w-8 tw:h-8" />,
|
||||
menu: <CoreSettingsMenu {...menuProps} />,
|
||||
},
|
||||
{
|
||||
t: 'UI Preferences',
|
||||
d: 'These preferences control the UI (User Interface) of the pattern editor',
|
||||
icon: <UiIcon className="tw-w-8 tw-h-8" />,
|
||||
icon: <UiIcon className="tw:w-8 tw:h-8" />,
|
||||
menu: <UiPreferencesMenu {...menuProps} />,
|
||||
},
|
||||
]
|
||||
|
@ -34,11 +34,11 @@ export const DraftMenu = ({ Design, pattern, state, update, i18n }) => {
|
|||
items.push(
|
||||
...sections.map((section) => [
|
||||
<>
|
||||
<h5 className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-justify-between tw-w-full tw-font-bold tw-text-lg">
|
||||
<h5 className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:justify-between tw:w-full tw:font-bold tw:text-lg">
|
||||
<span>{section.t}</span>
|
||||
{section.icon}
|
||||
</h5>
|
||||
<p className="tw-text-left">{section.d}</p>
|
||||
<p className="tw:text-left">{section.d}</p>
|
||||
</>,
|
||||
section.menu,
|
||||
section.name,
|
||||
|
|
|
@ -36,8 +36,8 @@ export const MenuConstantInput = ({
|
|||
<input
|
||||
type={type}
|
||||
className={`
|
||||
tw-daisy-input tw-daisy-input-bordered tw-w-full tw-text-base-content
|
||||
${changed ? 'tw-daisy-input-secondary' : 'tw-daisy-input-accent'}
|
||||
tw:daisy-input tw:daisy-input-bordered tw:w-full tw:text-base-content
|
||||
${changed ? 'tw:daisy-input-secondary' : 'tw:daisy-input-accent'}
|
||||
`}
|
||||
value={changed ? current : config.dflt}
|
||||
onChange={(evt) => updateHandler([name], evt.target.value)}
|
||||
|
@ -143,16 +143,16 @@ export const MenuListInput = ({
|
|||
onClick={() => handleChange(entry)}
|
||||
>
|
||||
<div
|
||||
className={`tw-w-full tw-flex ${
|
||||
className={`tw:w-full tw:flex ${
|
||||
sideBySide
|
||||
? 'tw-flex-row tw-justify-between tw-gap-2 tw-items-center'
|
||||
: 'tw-flex-col tw-items-start'
|
||||
? 'tw:flex-row tw:justify-between tw:gap-2 tw:items-center'
|
||||
: 'tw:flex-col tw:items-start'
|
||||
}`}
|
||||
>
|
||||
<div className="tw-font-semibold">{config.choiceTitles[entry]}</div>
|
||||
<div className="tw:font-semibold">{config.choiceTitles[entry]}</div>
|
||||
{compact || !config.choiceDescriptions ? null : (
|
||||
<div
|
||||
className={`${config.dense ? 'tw-text-sm tw-leading-5 tw-py-1' : 'tw-text-base'} tw-font-normal`}
|
||||
className={`${config.dense ? 'tw:text-sm tw:leading-5 tw:py-1' : 'tw:text-base'} tw:font-normal`}
|
||||
>
|
||||
{config.choiceDescriptions[entry]}
|
||||
</div>
|
||||
|
@ -178,7 +178,7 @@ export const MenuListToggle = ({ config, changed, updateHandler, name }) => {
|
|||
return (
|
||||
<input
|
||||
type="checkbox"
|
||||
className={`tw-daisy-toggle ${changed ? 'tw-daisy-toggle-accent' : 'tw-daisy-toggle-secondary'}`}
|
||||
className={`tw:daisy-toggle ${changed ? 'tw:daisy-toggle-accent' : 'tw:daisy-toggle-secondary'}`}
|
||||
checked={checked}
|
||||
onChange={doToggle}
|
||||
onClick={(evt) => evt.stopPropagation()}
|
||||
|
@ -296,7 +296,7 @@ export const MenuSliderInput = ({
|
|||
if (override)
|
||||
return (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-justify-between">
|
||||
<div className="tw:flex tw:flex-row tw:justify-between">
|
||||
<MenuEditOption
|
||||
{...{
|
||||
config,
|
||||
|
@ -314,17 +314,17 @@ export const MenuSliderInput = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-flex tw-flex-row tw-justify-between">
|
||||
<span className="tw-opacity-50">
|
||||
<div className="tw:flex tw:flex-row tw:justify-between">
|
||||
<span className="tw:opacity-50">
|
||||
<span dangerouslySetInnerHTML={{ __html: valFormatter(min) + suffix }} />
|
||||
</span>
|
||||
<div
|
||||
className={`tw-font-bold ${val === config.dflt ? 'tw-text-secondary' : 'tw-text-accent'}`}
|
||||
className={`tw:font-bold ${val === config.dflt ? 'tw:text-secondary' : 'tw:text-accent'}`}
|
||||
>
|
||||
<span dangerouslySetInnerHTML={{ __html: valFormatter(val) + suffix }} />
|
||||
{typeof config.toAbs === 'function' ? (
|
||||
<span>
|
||||
<span className="tw-px-2">|</span>
|
||||
<span className="tw:px-2">|</span>
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: formatMm(
|
||||
|
@ -340,7 +340,7 @@ export const MenuSliderInput = ({
|
|||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<span className="tw-opacity-50">
|
||||
<span className="tw:opacity-50">
|
||||
<span dangerouslySetInnerHTML={{ __html: valFormatter(max) + suffix }} />
|
||||
</span>
|
||||
</div>
|
||||
|
@ -349,8 +349,8 @@ export const MenuSliderInput = ({
|
|||
{...{ min, max, value: val, step: config.step || 0.1 }}
|
||||
onChange={(evt) => handleChange(evt.target.value)}
|
||||
className={`
|
||||
tw-daisy-range tw-daisy-range-sm tw-mt-1
|
||||
${changed ? 'tw-daisy-range-accent' : 'tw-daisy-range-secondary'}
|
||||
tw:daisy-range tw:daisy-range-sm tw:mt-1
|
||||
${changed ? 'tw:daisy-range-accent' : 'tw:daisy-range-secondary'}
|
||||
`}
|
||||
/>
|
||||
{children}
|
||||
|
@ -396,21 +396,21 @@ export const MenuEditOption = (props) => {
|
|||
return <p>This design option type does not have a component to handle manual input.</p>
|
||||
|
||||
return (
|
||||
<div className="tw-daisy-form-control tw-mb-2 tw-w-full">
|
||||
<div className="tw-daisy-label tw-font-medium tw-text-accent">
|
||||
<label className="tw-daisy-label-text">
|
||||
<div className="tw:daisy-form-control tw:mb-2 tw:w-full">
|
||||
<div className="tw:daisy-label tw:font-medium tw:text-accent">
|
||||
<label className="tw:daisy-label-text">
|
||||
<em>Enter a custom value</em>
|
||||
</label>
|
||||
{type === 'pct' && typeof config.fromAbs === 'function' ? (
|
||||
<label className="tw-daisy-label-text">
|
||||
<label className="tw:daisy-label-text">
|
||||
<KeyVal k="units" val={units} onClick={toggleInputUnits} color="secondary" />
|
||||
</label>
|
||||
) : null}
|
||||
</div>
|
||||
<label className="tw-daisy-input-group tw-daisy-input-group-sm tw-flex tw-flex-row tw-items-end tw-gap-2 tw--mt-4">
|
||||
<label className="tw:daisy-input-group tw:daisy-input-group-sm tw:flex tw:flex-row tw:items-end tw:gap-2 tw:-mt-4">
|
||||
<NumberInput value={manualEdit} update={setManualEdit} />
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-mt-4"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:mt-4"
|
||||
onClick={() => onUpdate(manualEdit, units)}
|
||||
>
|
||||
<ApplyIcon />
|
||||
|
@ -470,8 +470,8 @@ export const MenuOnlySettingInput = (props) => {
|
|||
const [design, name] = part.split('.')
|
||||
config.choiceTitles[part] = (
|
||||
<span>
|
||||
<span className="tw-font-medium tw-opacity-80 tw-capitalize">{design}</span>
|
||||
<span className="tw-font-medium tw-opacity-80 tw-capitalize tw-px-2">»</span>
|
||||
<span className="tw:font-medium tw:opacity-80 tw:capitalize">{design}</span>
|
||||
<span className="tw:font-medium tw:opacity-80 tw:capitalize tw:px-2">»</span>
|
||||
{i18n[design].en.p[name]}
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -29,7 +29,7 @@ export const LayoutSettingsMenu = ({ update, state, Design }) => {
|
|||
orientation: ({ current, changed }) => (
|
||||
<MenuHighlightValue changed={changed}>
|
||||
<PatternIcon
|
||||
className={`tw-w-6 tw-h-6 tw-text-inherit ${current === 'landscape' ? 'tw--rotate-90' : ''}`}
|
||||
className={`tw:w-6 tw:h-6 tw:text-inherit ${current === 'landscape' ? 'tw:-rotate-90' : ''}`}
|
||||
/>
|
||||
</MenuHighlightValue>
|
||||
),
|
||||
|
@ -67,8 +67,8 @@ const PrintActions = ({ state, update }) => (
|
|||
<SubAccordion
|
||||
items={[
|
||||
[
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-gap2 tw-justify-between" key={1}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:gap2 tw:justify-between" key={1}>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
<LeftRightIcon />
|
||||
<span>{'workbench:partTransfo'}</span>
|
||||
</div>
|
||||
|
@ -78,7 +78,7 @@ const PrintActions = ({ state, update }) => (
|
|||
key={2}
|
||||
update={() => update.state.ui('hideMovableButtons', state.ui.hideMovableButtons ? false : true)}
|
||||
label={
|
||||
<span className="tw-text-base tw-font-normal">{'workbench:partTransfoDesc'}</span>
|
||||
<span className="tw:text-base tw:font-normal">{'workbench:partTransfoDesc'}</span>
|
||||
}
|
||||
list={[
|
||||
{
|
||||
|
@ -97,8 +97,8 @@ const PrintActions = ({ state, update }) => (
|
|||
'partTransfo',
|
||||
],
|
||||
[
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-gap2 tw-justify-between" key={1}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:gap2 tw:justify-between" key={1}>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
||||
<ResetIcon />
|
||||
<span>{'workbench:resetPrintLayout'}</span>
|
||||
</div>
|
||||
|
@ -108,7 +108,7 @@ const PrintActions = ({ state, update }) => (
|
|||
<Fragment key={2}>
|
||||
<p>{'workbench:resetPrintLayoutDesc'}</p>
|
||||
<button
|
||||
className={`${horFlexClasses} tw-btn tw-btn-warning tw-btn-outline tw-w-full`}
|
||||
className={`${horFlexClasses} tw:btn tw:btn-warning tw:btn-outline tw:w-full`}
|
||||
onClick={() => update.ui(['layouts', 'print'])}
|
||||
>
|
||||
<ResetIcon />
|
||||
|
|
|
@ -81,12 +81,12 @@ export const TestMeasurementsMenu = ({ Design, state, update }) => {
|
|||
const SampleOptionButton = ({ name, i18n, update }) => (
|
||||
<button
|
||||
className={
|
||||
'tw-daisy-btn tw-daisy-btn-outline tw-daisy-btn-sm tw-mx-2 ' +
|
||||
'tw-daisy-btn-secondary tw-flex tw-flex-row tw-items-center tw-justify-between'
|
||||
'tw:daisy-btn tw:daisy-btn-outline tw:daisy-btn-sm tw:mx-2 ' +
|
||||
'tw:daisy-btn-secondary tw:flex tw:flex-row tw:items-center tw:justify-between'
|
||||
}
|
||||
onClick={() => update.settings('sample', { type: 'option', option: name })}
|
||||
>
|
||||
<BeakerIcon className="tw-w-5 tw-h-5" />
|
||||
<BeakerIcon className="tw:w-5 tw:h-5" />
|
||||
<span>{i18n.en.o[name].t}</span>
|
||||
</button>
|
||||
)
|
||||
|
@ -94,12 +94,12 @@ const SampleOptionButton = ({ name, i18n, update }) => (
|
|||
const SampleMeasurementButton = ({ name, i18n, update }) => (
|
||||
<button
|
||||
className={
|
||||
'tw-daisy-btn tw-daisy-btn-outline tw-daisy-btn-sm tw-mx-2 ' +
|
||||
'tw-daisy-btn-secondary tw-flex tw-flex-row tw-items-center tw-justify-between'
|
||||
'tw:daisy-btn tw:daisy-btn-outline tw:daisy-btn-sm tw:mx-2 ' +
|
||||
'tw:daisy-btn-secondary tw:flex tw:flex-row tw:items-center tw:justify-between'
|
||||
}
|
||||
onClick={() => update.settings('sample', { type: 'option', option: name })}
|
||||
>
|
||||
<BeakerIcon className="tw-w-5 tw-h-5" />
|
||||
<BeakerIcon className="tw:w-5 tw:h-5" />
|
||||
<span>{measurementsTranslations[name]}</span>
|
||||
</button>
|
||||
)
|
||||
|
|
|
@ -50,7 +50,7 @@ export const MenuDegOptionValue = ({ config, current, changed }) => (
|
|||
* @param {Function} children - The React children
|
||||
*/
|
||||
export const MenuHighlightValue = ({ changed, children }) => (
|
||||
<span className={changed ? 'tw-text-accent' : ''}> {children} </span>
|
||||
<span className={changed ? 'tw:text-accent' : ''}> {children} </span>
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Collection } from '@freesewing/react/components/Collection'
|
|||
* @param {Object} update - ViewWrapper state update object
|
||||
*/
|
||||
export const DesignsView = ({ designs = {}, update }) => (
|
||||
<div className="tw-text-center tw-mt-8 tw-mb-24 tw-p-2 lg: tw-p-8">
|
||||
<div className="tw:text-center tw:mt-8 tw:mb-24 tw:p-2 lg: tw:p-8">
|
||||
<h1>Choose a design from the FreeSewing collection</h1>
|
||||
<Collection
|
||||
editor
|
||||
|
|
|
@ -19,11 +19,11 @@ export const DocsView = ({ state, config, update }) => {
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-2xl tw-px-4 tw-mb-8">
|
||||
<div className="tw:m-auto tw:mt-8 tw:max-w-2xl tw:px-4 tw:mb-8">
|
||||
<H1>Documenation</H1>
|
||||
<Popout link>
|
||||
<H5>Understanding the FreeSewing Pattern Editor</H5>
|
||||
<p className="tw-text-lg">
|
||||
<p className="tw:text-lg">
|
||||
Please refer to the pattern editor documentation at:
|
||||
<br />
|
||||
<b>
|
||||
|
|
|
@ -33,21 +33,21 @@ export const DraftErrorHandler = ({ failure, errors }) => {
|
|||
<Link href="https://codeberg.org/freesewing/freesewing/issues">report an issue</Link>.
|
||||
</p>
|
||||
|
||||
<div className={'tw-mt-4'}>
|
||||
<div className={'tw:mt-4'}>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary`}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
>
|
||||
<ExpandIcon />
|
||||
Show error details
|
||||
</button>
|
||||
<button className={`tw-daisy-btn tw-ml-4`} onClick={() => setHidden(true)}>
|
||||
<button className={`tw:daisy-btn tw:ml-4`} onClick={() => setHidden(true)}>
|
||||
<CloseIcon />
|
||||
Hide
|
||||
</button>
|
||||
</div>
|
||||
{expanded ? (
|
||||
<div className={'tw-mt-8'}>
|
||||
<div className={'tw:mt-8'}>
|
||||
{failure ? <LogEntry key="failure" logEntry={failure} /> : null}
|
||||
{errors.map((line, i) => (
|
||||
<LogEntry key={i} logEntry={line} />
|
||||
|
|
|
@ -65,7 +65,7 @@ export const DraftView = ({ Design, state, update, config, plugins = [], PluginO
|
|||
<DraftErrorHandler {...{ failure, errors }} />
|
||||
<PluginOutput {...{ pattern, Design, state, update, config }} />
|
||||
<ZoomablePattern update={update}>
|
||||
<div className="tw-w-full tw-h-full" dangerouslySetInnerHTML={{ __html }} />
|
||||
<div className="tw:w-full tw:h-full" dangerouslySetInnerHTML={{ __html }} />
|
||||
</ZoomablePattern>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -27,9 +27,9 @@ export const EditSettingsView = (props) => {
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-4xl tw-px-4 tw-mb-8">
|
||||
<div className="tw:m-auto tw:mt-8 tw:max-w-4xl tw:px-4 tw:mb-8">
|
||||
<H1>Edit settings by hand</H1>
|
||||
<p className="tw-mb-4">
|
||||
<p className="tw:mb-4">
|
||||
You can hand-edit your pattern settings below.
|
||||
<br />
|
||||
The changes will not take effect until you click the <b>Save Settings</b> button at the
|
||||
|
@ -106,22 +106,22 @@ export const PrimedSettingsEditor = (props) => {
|
|||
<>
|
||||
<H4>You have made changes</H4>
|
||||
<p>Your settings have been edited, and are now different from the editor settings.</p>
|
||||
<div className="tw-grid tw-grid-cols-1 lg:tw-grid-cols-3 tw-gap-2 tw-w-full">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:lg:grid-cols-3 tw:gap-2 tw:w-full">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline"
|
||||
onClick={() => setShowDelta(!showDelta)}
|
||||
>
|
||||
{showDelta ? 'Hide' : 'Show'} Changes
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-flex tw-flex-row tw-items-center tw-justify-between"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:flex tw:flex-row tw:items-center tw:justify-between"
|
||||
onClick={save}
|
||||
>
|
||||
<OkIcon stroke={3} />
|
||||
Save Settings
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-error tw-daisy-btn-outline tw-flex tw-flex-row tw-items-center tw-justify-between"
|
||||
className="tw:daisy-btn tw:daisy-btn-error tw:daisy-btn-outline tw:flex tw:flex-row tw:items-center tw:justify-between"
|
||||
onClick={revert}
|
||||
>
|
||||
<ResetIcon />
|
||||
|
@ -129,7 +129,7 @@ export const PrimedSettingsEditor = (props) => {
|
|||
</button>
|
||||
</div>
|
||||
{showDelta ? (
|
||||
<div className="tw-my-4 tw-w-full tw-overflow-scroll">
|
||||
<div className="tw:my-4 tw:w-full tw:overflow-scroll">
|
||||
<DiffViewer
|
||||
oldValue={yaml.stringify(state.settings)}
|
||||
newValue={yaml.stringify(settings)}
|
||||
|
|
|
@ -52,11 +52,11 @@ export const ExportView = (props) => {
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-2xl tw-px-4 tw-mb-8">
|
||||
<div className="tw:m-auto tw:mt-8 tw:max-w-2xl tw:px-4 tw:mb-8">
|
||||
<H1>Export Pattern</H1>
|
||||
<H2>Share your pattern</H2>
|
||||
<p>If you merely want to share your pattern with others, you can copy these URLs:</p>
|
||||
<div className="tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-2 tw-mt-2 ">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-2 tw:mt-2 ">
|
||||
<CopyToClipboardButton content={urls.a} update={update}>
|
||||
Pattern and Measurements
|
||||
</CopyToClipboardButton>
|
||||
|
@ -64,11 +64,11 @@ export const ExportView = (props) => {
|
|||
Pattern only
|
||||
</CopyToClipboardButton>
|
||||
</div>
|
||||
<details className="tw-pt-2">
|
||||
<details className="tw:pt-2">
|
||||
<summary>
|
||||
<span className={linkClasses}>Explain these buttons</span>
|
||||
</summary>
|
||||
<div className="tw-ml-4 tw-border-l-2 tw-pl-4">
|
||||
<div className="tw:ml-4 tw:border-l-2 tw:pl-4">
|
||||
<H5>Pattern and Measurements</H5>
|
||||
<p>
|
||||
Use the <b>Pattern and Measurements</b> URL to share this pattern exactly as-is,
|
||||
|
@ -77,8 +77,8 @@ export const ExportView = (props) => {
|
|||
<Highlight noCopy title="URL" language="URL">
|
||||
{urls.a}
|
||||
</Highlight>
|
||||
<div className="tw-text-sm tw--mt-3 tw-flex tw-flex-row tw-gap-2 tw-items-center tw-pl-4 tw-mb-4">
|
||||
<TipIcon className="tw-w-5 tw-h-5 tw-text-success" />
|
||||
<div className="tw:text-sm tw:-mt-3 tw:flex tw:flex-row tw:gap-2 tw:items-center tw:pl-4 tw:mb-4">
|
||||
<TipIcon className="tw:w-5 tw:h-5 tw:text-success" />
|
||||
Use this to allow others to troubleshoot your pattern.
|
||||
</div>
|
||||
<H5>Pattern only</H5>
|
||||
|
@ -88,20 +88,20 @@ export const ExportView = (props) => {
|
|||
<Highlight noCopy title="URL" language="URL">
|
||||
{urls.b}
|
||||
</Highlight>
|
||||
<div className="tw-text-sm tw--mt-3 tw-flex tw-flex-row tw-gap-2 tw-items-center tw-pl-4">
|
||||
<TipIcon className="tw-w-5 tw-h-5 tw-text-success" />
|
||||
<div className="tw:text-sm tw:-mt-3 tw:flex tw:flex-row tw:gap-2 tw:items-center tw:pl-4">
|
||||
<TipIcon className="tw:w-5 tw:h-5 tw:text-success" />
|
||||
Use this to allow others to recreate this pattern for themselves.
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<H2>Export for printing</H2>
|
||||
<p>You can export your pattern in a variety of page formats for printing:</p>
|
||||
<div className="tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-2">
|
||||
<div className="tw-flex tw-flex-col tw-gap-2 tw-max-w-md">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-2">
|
||||
<div className="tw:flex tw:flex-col tw:gap-2 tw:max-w-md">
|
||||
<H3>ISO paper sizes</H3>
|
||||
{['a4', 'a3', 'a2', 'a1', 'a0'].map((format) => (
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-primary tw-uppercase`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-primary tw:uppercase`}
|
||||
onClick={() => exportPattern({ ...exportProps, format })}
|
||||
>
|
||||
<PrintIcon />
|
||||
|
@ -109,11 +109,11 @@ export const ExportView = (props) => {
|
|||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-col tw-gap-2 tw-max-w-md">
|
||||
<div className="tw:flex tw:flex-col tw:gap-2 tw:max-w-md">
|
||||
<H3>Other paper sizes</H3>
|
||||
{['letter', 'legal', 'tabloid'].map((format) => (
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-primary tw-uppercase`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-primary tw:uppercase`}
|
||||
onClick={() => exportPattern({ ...exportProps, format })}
|
||||
>
|
||||
<PrintIcon />
|
||||
|
@ -126,10 +126,10 @@ export const ExportView = (props) => {
|
|||
<p>
|
||||
We recommend SVG for editing, but we also provide a full-sized PDF if you prefer that.
|
||||
</p>
|
||||
<div className="tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-2 tw-mt-2">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-2 tw:mt-2">
|
||||
{['svg', 'pdf'].map((format) => (
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-primary tw-uppercase`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-primary tw:uppercase`}
|
||||
onClick={() => exportPattern({ ...exportProps, format })}
|
||||
>
|
||||
<EditIcon />
|
||||
|
@ -139,10 +139,10 @@ export const ExportView = (props) => {
|
|||
</div>
|
||||
<H2>Export as code</H2>
|
||||
<p>This is all you need to reconstruct this pattern using FreeSewing' software:</p>
|
||||
<div className="tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-2 tw-mt-2">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-2 tw:mt-2">
|
||||
{['json', 'yaml'].map((format) => (
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-primary tw-uppercase`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-primary tw:uppercase`}
|
||||
onClick={() => exportPattern({ ...exportProps, format })}
|
||||
>
|
||||
<CodeIcon />
|
||||
|
|
|
@ -68,7 +68,7 @@ export const InspectView = ({ Design, state, update, config }) => {
|
|||
<Xray
|
||||
renderProps={renderProps}
|
||||
drillProps={{ info }}
|
||||
className={`freesewing pattern tw-w-full ${state.ui?.rotate ? 'tw--rotate-90' : ''}`}
|
||||
className={`freesewing pattern tw:w-full ${state.ui?.rotate ? 'tw:-rotate-90' : ''}`}
|
||||
strings={strings}
|
||||
/>
|
||||
</ZoomablePattern>
|
||||
|
|
|
@ -3,7 +3,7 @@ import Markdown from 'react-markdown'
|
|||
|
||||
export const LogEntry = ({ logEntry }) => (
|
||||
<>
|
||||
<div className="log-entry tw-mb-2">
|
||||
<div className="log-entry tw:mb-2">
|
||||
<Markdown>{Array.isArray(logEntry) ? logEntry[0] : logEntry}</Markdown>
|
||||
</div>
|
||||
{/* uncomment to enable stacktrace view
|
||||
|
|
|
@ -26,7 +26,7 @@ export const LogView = (props) => {
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-2xl tw-px-4 tw-mb-8">
|
||||
<div className="tw:m-auto tw:mt-8 tw:max-w-2xl tw:px-4 tw:mb-8">
|
||||
<H1>Pattern Logs</H1>
|
||||
<Tabs tabs="Set 0 Logs, Pattern Logs">
|
||||
<Tab tabId="Set 0 Logs">
|
||||
|
|
|
@ -22,7 +22,7 @@ import { HeaderMenu } from '../HeaderMenu.mjs'
|
|||
import { H1, H5 } from '@freesewing/react/components/Heading'
|
||||
|
||||
const iconClasses = {
|
||||
className: 'tw-w-8 tw-h-8 md:tw-w-10 md:tw-h-10 lg:tw-w-12 lg:tw-h-12 tw-shrink-0',
|
||||
className: 'tw:w-8 tw:h-8 tw:md:w-10 tw:md:h-10 tw:lg:w-12 tw:lg:h-12 tw:shrink-0',
|
||||
stroke: 1.5,
|
||||
}
|
||||
|
||||
|
@ -77,13 +77,13 @@ export const MeasurementsView = ({
|
|||
// User measurement set
|
||||
update.settings(['metadata'], { setName: set.name })
|
||||
update.notifySuccess(
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-w-full tw-flex-wrap tw-gap-2">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-between tw:w-full tw:flex-wrap tw:gap-2">
|
||||
<span>Measurements loaded</span>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-success tw-daisy-btn-outline tw-border-white"
|
||||
className="tw:daisy-btn tw:daisy-btn-success tw:daisy-btn-outline tw:border-white"
|
||||
onClick={() => update.view('draft')}
|
||||
>
|
||||
<span className="tw-text-white">Load Draft View</span>
|
||||
<span className="tw:text-white">Load Draft View</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
@ -95,11 +95,11 @@ export const MeasurementsView = ({
|
|||
items.push(
|
||||
[
|
||||
<Fragment key={1}>
|
||||
<div className={`${horFlexClasses} tw-w-full`}>
|
||||
<div className={`${horFlexClasses} tw:w-full`}>
|
||||
<H5 id="ownsets">Choose one of your own measurements sets</H5>
|
||||
<MeasurementsSetIcon {...iconClasses} />
|
||||
</div>
|
||||
<p className="tw-text-left">
|
||||
<p className="tw:text-left">
|
||||
Pick any of your own measurements sets that have all required measurements to generate
|
||||
this pattern.
|
||||
</p>
|
||||
|
@ -115,11 +115,11 @@ export const MeasurementsView = ({
|
|||
],
|
||||
[
|
||||
<Fragment key={1}>
|
||||
<div className={`${horFlexClasses} tw-w-full`}>
|
||||
<div className={`${horFlexClasses} tw:w-full`}>
|
||||
<H5 id="bookmarkedsets">Choose one of the measurements sets you have bookmarked</H5>
|
||||
<BookmarkIcon {...iconClasses} />
|
||||
</div>
|
||||
<p className="tw-text-left">
|
||||
<p className="tw:text-left">
|
||||
If you have bookmarked any measurements sets, you can select from those too.
|
||||
</p>
|
||||
</Fragment>,
|
||||
|
@ -134,11 +134,11 @@ export const MeasurementsView = ({
|
|||
],
|
||||
[
|
||||
<Fragment key={1}>
|
||||
<div className={`${horFlexClasses} tw-w-full`}>
|
||||
<div className={`${horFlexClasses} tw:w-full`}>
|
||||
<H5 id="curatedsets">Choose one of FreeSewing's curated measurements sets</H5>
|
||||
<CuratedMeasurementsSetIcon {...iconClasses} />
|
||||
</div>
|
||||
<p className="tw-text-left">
|
||||
<p className="tw:text-left">
|
||||
If you're just looking to try out our platform, you can select from our list of
|
||||
curated measurements sets.
|
||||
</p>
|
||||
|
@ -148,11 +148,11 @@ export const MeasurementsView = ({
|
|||
],
|
||||
[
|
||||
<Fragment key={1}>
|
||||
<div className={`${horFlexClasses} tw-w-full`}>
|
||||
<div className={`${horFlexClasses} tw:w-full`}>
|
||||
<H5 id="loadid">Load a measurements set by ID</H5>
|
||||
<FingerprintIcon {...iconClasses} />
|
||||
</div>
|
||||
<p className="tw-text-left">
|
||||
<p className="tw:text-left">
|
||||
If you know the ID of a measurements set — either one of your own or a public set — we
|
||||
can load it for you.
|
||||
</p>
|
||||
|
@ -164,11 +164,11 @@ export const MeasurementsView = ({
|
|||
// Manual editing is always an option
|
||||
items.push([
|
||||
<Fragment key={1}>
|
||||
<div className={`${horFlexClasses} tw-w-full`}>
|
||||
<div className={`${horFlexClasses} tw:w-full`}>
|
||||
<H5 id="editmeasurements">Edit measurements by hand</H5>
|
||||
<EditIcon {...iconClasses} />
|
||||
</div>
|
||||
<p className="tw-text-left">You can manually set or override measurements below.</p>
|
||||
<p className="tw:text-left">You can manually set or override measurements below.</p>
|
||||
</Fragment>,
|
||||
<MeasurementsEditor
|
||||
key={2}
|
||||
|
@ -180,7 +180,7 @@ export const MeasurementsView = ({
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-max-w-7xl tw-mt-8 tw-mx-auto tw-px-4 tw-mb-4">
|
||||
<div className="tw:max-w-7xl tw:mt-8 tw:mx-auto tw:px-4 tw:mb-4">
|
||||
<H1>Measurements</H1>
|
||||
{missingMeasurements && missingMeasurements.length > 0 ? (
|
||||
<Popout note dense noP>
|
||||
|
@ -188,11 +188,11 @@ export const MeasurementsView = ({
|
|||
To generate this pattern, we need {missingMeasurements.length} additional measurement
|
||||
{missingMeasurements.length === 1 ? '' : 's'}:
|
||||
</h3>
|
||||
<ol className="tw-list tw-list-inside tw-flex tw-flex-row tw-flex-wrap tw-ml-0 tw-pl-0">
|
||||
<ol className="tw:list tw:list-inside tw:flex tw:flex-row tw:flex-wrap tw:ml-0 tw:pl-0">
|
||||
{missingMeasurements.map((m, i) => (
|
||||
<li key={i} className="tw-flex">
|
||||
{i > 0 ? <span className="tw-pr-2">,</span> : null}
|
||||
<span className="tw-font-medium">{measurementsTranslations[m]}</span>
|
||||
<li key={i} className="tw:flex">
|
||||
{i > 0 ? <span className="tw:pr-2">,</span> : null}
|
||||
<span className="tw:font-medium">{measurementsTranslations[m]}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
@ -200,15 +200,15 @@ export const MeasurementsView = ({
|
|||
) : (
|
||||
<Popout tip dense noP>
|
||||
<H5>We have all required measurements to draft this pattern</H5>
|
||||
<div className="tw-flex tw-flex-row tw-flex-wrap tw-gap-2 tw-mt-2">
|
||||
<div className="tw:flex tw:flex-row tw:flex-wrap tw:gap-2 tw:mt-2">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary"
|
||||
onClick={() => update.view('draft')}
|
||||
>
|
||||
Draft Pattern
|
||||
</button>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline"
|
||||
onClick={() => update.view('picker')}
|
||||
>
|
||||
Choose a different view
|
||||
|
@ -228,7 +228,7 @@ const LoadMeasurementsSetById = ({ loadMeasurements, update }) => {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-items-end">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:items-end">
|
||||
<NumberInput
|
||||
label="Measurements Set ID"
|
||||
update={setId}
|
||||
|
@ -236,7 +236,7 @@ const LoadMeasurementsSetById = ({ loadMeasurements, update }) => {
|
|||
valid={(val) => Number(val) == val}
|
||||
/>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary"
|
||||
onClick={() => loadMeasurementsSet(id, backend, loadMeasurements, update)}
|
||||
>
|
||||
Load set
|
||||
|
@ -256,13 +256,13 @@ async function loadMeasurementsSet(id, backend, loadMeasurements, update) {
|
|||
loadMeasurements(result[1].set)
|
||||
update.clearLoading()
|
||||
update.notifySuccess(
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-w-full tw-flex-wrap tw-gap-2">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-between tw:w-full tw:flex-wrap tw:gap-2">
|
||||
<span>Measurements set loaded</span>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-success tw-daisy-btn-outline tw-border-white"
|
||||
className="tw:daisy-btn tw:daisy-btn-success tw:daisy-btn-outline tw:border-white"
|
||||
onClick={() => update.view('draft')}
|
||||
>
|
||||
<span className="tw-text-white">Load Draft View</span>
|
||||
<span className="tw:text-white">Load Draft View</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -92,7 +92,7 @@ export const SaveView = ({ config, state, update }) => {
|
|||
return (
|
||||
<RoleBlock user>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-2xl tw-px-4">
|
||||
<div className="tw:m-auto tw:mt-8 tw:max-w-2xl tw:px-4">
|
||||
{saveAs && saveAs.pattern ? (
|
||||
<>
|
||||
<h2>Save Pattern</h2>
|
||||
|
@ -103,16 +103,16 @@ export const SaveView = ({ config, state, update }) => {
|
|||
</Popout>
|
||||
)}
|
||||
<button
|
||||
className={`${classeshorFlexNoSm} tw-btn tw-btn-primary tw-btn-lg tw-w-full tw-mt-2 tw-my-8`}
|
||||
className={`${classeshorFlexNoSm} tw:btn tw:btn-primary tw:btn-lg tw:w-full tw:mt-2 tw:my-8`}
|
||||
onClick={savePattern}
|
||||
>
|
||||
<SaveIcon className="tw-h-8 tw-w-8" />
|
||||
<SaveIcon className="tw:h-8 tw:w-8" />
|
||||
Save Patter #{saveAs.pattern}
|
||||
</button>
|
||||
</>
|
||||
) : null}
|
||||
<H1>Save As New Pattern</H1>
|
||||
<div className="tw-mb-4">
|
||||
<div className="tw:mb-4">
|
||||
<StringInput
|
||||
label="Pattern title"
|
||||
current={name}
|
||||
|
@ -121,20 +121,20 @@ export const SaveView = ({ config, state, update }) => {
|
|||
labelBR={
|
||||
<>
|
||||
{withNotes ? (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-4">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-4">
|
||||
<button
|
||||
className={`tw-font-bold ${linkClasses}`}
|
||||
className={`tw:font-bold ${linkClasses}`}
|
||||
onClick={() => setWithNotes(false)}
|
||||
>
|
||||
Hide notes
|
||||
</button>
|
||||
<button className={`tw-font-bold ${linkClasses}`} onClick={addSettingsToNotes}>
|
||||
<button className={`tw:font-bold ${linkClasses}`} onClick={addSettingsToNotes}>
|
||||
Add settings to notes
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
className={`tw-font-bold ${linkClasses}`}
|
||||
className={`tw:font-bold ${linkClasses}`}
|
||||
onClick={() => setWithNotes(true)}
|
||||
>
|
||||
Add notes
|
||||
|
@ -150,24 +150,24 @@ export const SaveView = ({ config, state, update }) => {
|
|||
update={setNotes}
|
||||
/>
|
||||
) : null}
|
||||
<div className="tw-flex tw-flex-row tw-gap-2 tw-mt-8">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2 tw:mt-8">
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary lg:tw-daisy-btn-lg tw-daisy-btn-outline`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-primary lg:tw:daisy-btn-lg tw:daisy-btn-outline`}
|
||||
onClick={update.viewBack}
|
||||
title="Cancel"
|
||||
>
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
<button
|
||||
className={`tw-flex tw-flex-row tw-items-center tw-justify-between tw-daisy-btn tw-daisy-btn-primary lg:tw-daisy-btn-lg tw-grow`}
|
||||
className={`tw:flex tw:flex-row tw:items-center tw:justify-between tw:daisy-btn tw:daisy-btn-primary lg:tw:daisy-btn-lg tw:grow`}
|
||||
onClick={saveAsNewPattern}
|
||||
title="Save as new pattern"
|
||||
>
|
||||
<SaveAsIcon className="tw-w-8 tw-h-8" />
|
||||
<SaveAsIcon className="tw:w-8 tw:h-8" />
|
||||
<span>Save as new pattern</span>
|
||||
</button>
|
||||
</div>
|
||||
<p className="tw-text-sm tw-text-right">
|
||||
<p className="tw:text-sm tw:text-right">
|
||||
To access your saved patterns, go to:
|
||||
<b>
|
||||
{' '}
|
||||
|
|
|
@ -92,22 +92,22 @@ export const TestView = ({ Design, state, update, config }) => {
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update, Design }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-4xl tw-px-4 tw-mb-8">
|
||||
<div className="tw:m-auto tw:mt-8 tw:max-w-4xl tw:px-4 tw:mb-8">
|
||||
<H1>Test Pattern</H1>
|
||||
<div className="tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 lg:tw-gap-4">
|
||||
<div className="tw-flex tw-flex-col tw-gap-4">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:lg:gap-4">
|
||||
<div className="tw:flex tw:flex-col tw:gap-4">
|
||||
<H3>Test Design Options</H3>
|
||||
<SampleOptionsMenu {...{ Design, state, update }} />
|
||||
</div>
|
||||
{trm.length > 0 ? (
|
||||
<div className="tw-flex tw-flex-col tw-gap-4">
|
||||
<div className="tw:flex tw:flex-col tw:gap-4">
|
||||
<H3>Test Measurements</H3>
|
||||
<H4>Required Measurements</H4>
|
||||
<div className="">
|
||||
{trm.map(({ t, m }) => (
|
||||
<button
|
||||
key={m}
|
||||
className="tw-my-0.5 tw-block tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline tw-daisy-btn-xs"
|
||||
className="tw:my-0.5 tw:block tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline tw:daisy-btn-xs"
|
||||
onClick={() =>
|
||||
update.settings(['sample'], { type: 'measurement', measurement: m })
|
||||
}
|
||||
|
@ -117,13 +117,13 @@ export const TestView = ({ Design, state, update, config }) => {
|
|||
))}
|
||||
</div>
|
||||
{tom.length > 0 ? (
|
||||
<div className="tw-flex tw-flex-col tw-gap-4">
|
||||
<div className="tw:flex tw:flex-col tw:gap-4">
|
||||
<H4>Optional Measurements</H4>
|
||||
<div className="">
|
||||
{tom.map(({ t, m }) => (
|
||||
<button
|
||||
key={m}
|
||||
className="tw-my-0.5 tw-block tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline tw-daisy-btn-xs"
|
||||
className="tw:my-0.5 tw:block tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline tw:daisy-btn-xs"
|
||||
onClick={() =>
|
||||
update.settings(['sample'], { type: 'measurement', measurement: m })
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ const SampleOptionsSubMenu = ({ structure, update, level = 1 }) => {
|
|||
output.push(
|
||||
<button
|
||||
key={name}
|
||||
className="tw-my-0.5 tw-block tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline tw-daisy-btn-xs"
|
||||
className="tw:my-0.5 tw:block tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline tw:daisy-btn-xs"
|
||||
onClick={() => update.settings(['sample'], { type: 'option', option: name })}
|
||||
>
|
||||
{struct.title}
|
||||
|
@ -188,7 +188,7 @@ const SampleOptionsSubMenu = ({ structure, update, level = 1 }) => {
|
|||
if (struct.isGroup) {
|
||||
output.push(
|
||||
<H5 key={name}>
|
||||
<span className="tw-capitalize">{name}</span>
|
||||
<span className="tw:capitalize">{name}</span>
|
||||
</H5>
|
||||
)
|
||||
output.push(
|
||||
|
@ -202,5 +202,5 @@ const SampleOptionsSubMenu = ({ structure, update, level = 1 }) => {
|
|||
}
|
||||
}
|
||||
|
||||
return <div className="tw-pl-2 tw-border-l-2">{output}</div>
|
||||
return <div className="tw:pl-2 tw:border-l-2">{output}</div>
|
||||
}
|
||||
|
|
|
@ -22,16 +22,16 @@ export const UndosView = ({ Design, update, state, config }) => {
|
|||
return (
|
||||
<>
|
||||
<HeaderMenu {...{ update, Design, config, state }} />
|
||||
<div className="tw-text-left tw-mt-8 tw-mb-24 tw-px-4 tw-max-w-xl tw-mx-auto">
|
||||
<div className="tw:text-left tw:mt-8 tw:mb-24 tw:px-4 tw:max-w-xl tw:mx-auto">
|
||||
<H1>Undo History</H1>
|
||||
<p className="tw-mb-4">Time-travel through your recent pattern changes.</p>
|
||||
<p className="tw:mb-4">Time-travel through your recent pattern changes.</p>
|
||||
{steps.length < 1 ? (
|
||||
<Popout note>
|
||||
<h4>Your undo history is currently empty</h4>
|
||||
<p>When you make changes to your pattern, they will show up here.</p>
|
||||
<p>For example, you can click the button below to change the pattern rotation:</p>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-capitalize"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize"
|
||||
onClick={() => update.settings('ui.rotate', state.settings?.ui?.rotate ? 0 : 1)}
|
||||
>
|
||||
Example: Rotate pattern
|
||||
|
@ -43,7 +43,7 @@ export const UndosView = ({ Design, update, state, config }) => {
|
|||
<MiniTip>
|
||||
Click on any change to undo all changes up to, and including, that change.
|
||||
</MiniTip>
|
||||
<div className="tw-flex tw-flex-col tw-gap-2 tw-mt-4">
|
||||
<div className="tw:flex tw:flex-col tw:gap-2 tw:mt-4">
|
||||
{steps.map((step, index) => (
|
||||
<UndoStep key={step.time} {...{ step, update, state, Design, index }} />
|
||||
))}
|
||||
|
@ -97,8 +97,8 @@ export const UndoStep = ({ update, state, step, Design, compact = false, index =
|
|||
if (compact)
|
||||
return (
|
||||
<ButtonFrame dense onClick={() => update.restore(index, state._)}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-align-start tw-gap-2 tw-w-full">
|
||||
<UndoIcon text={index} className="tw-w-5 tw-h-5 tw-text-secondary" />
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:align-start tw:gap-2 tw:w-full">
|
||||
<UndoIcon text={index} className="tw:w-5 tw:h-5 tw:text-secondary" />
|
||||
{data.msg ? data.msg : data.title}
|
||||
</div>
|
||||
</ButtonFrame>
|
||||
|
@ -106,20 +106,20 @@ export const UndoStep = ({ update, state, step, Design, compact = false, index =
|
|||
|
||||
return (
|
||||
<>
|
||||
<p className="tw-text-sm tw-italic tw-font-medium tw-opacity-70 tw-text-right tw-p-0 tw-tw-m-0 tw--mb-2 tw-pr-2">
|
||||
<p className="tw:text-sm tw:italic tw:font-medium tw:opacity-70 tw:text-right tw:p-0 tw:tw:m-0 tw:-mb-2 tw:pr-2">
|
||||
<UndoStepTimeAgo step={step} />
|
||||
</p>
|
||||
<ButtonFrame onClick={() => update.restore(index, state._)}>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-gap-2 tw-w-full tw-m-0 tw-p-0 tw--mt-2 tw-text-lg">
|
||||
<span className="tw-flex tw-flex-row tw-gap-2 tw-items-center">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-between tw:gap-2 tw:w-full tw:m-0 tw:p-0 tw:-mt-2 tw:text-lg">
|
||||
<span className="tw:flex tw:flex-row tw:gap-2 tw:items-center">
|
||||
{data.fieldIcon || null}
|
||||
{data.title}
|
||||
</span>
|
||||
<span className="tw-opacity-70 tw-flex tw-flex-row tw-gap-1 tw-items-center tw-text-base">
|
||||
<span className="tw:opacity-70 tw:flex tw:flex-row tw:gap-1 tw:items-center tw:text-base">
|
||||
{data.icon || null} {data.menu}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-row tw-gap-1 tw-items-center tw-align-start tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:gap-1 tw:items-center tw:align-start tw:w-full">
|
||||
{data.msg ? (
|
||||
data.msg
|
||||
) : (
|
||||
|
@ -127,8 +127,8 @@ export const UndoStep = ({ update, state, step, Design, compact = false, index =
|
|||
<span className="">
|
||||
{Array.isArray(data.newVal) ? data.newVal.join(', ') : data.newVal}
|
||||
</span>
|
||||
<LeftIcon className="tw-w-4 tw-h-4 tw-text-secondary tw-shrink-0" stroke={4} />
|
||||
<span className="tw-line-through tw-decoration-1 tw-opacity-70">
|
||||
<LeftIcon className="tw:w-4 tw:h-4 tw:text-secondary tw:shrink-0" stroke={4} />
|
||||
<span className="tw:line-through tw:decoration-1 tw:opacity-70">
|
||||
{Array.isArray(data.oldVal) ? data.oldVal.join(', ') : data.oldVal}
|
||||
</span>
|
||||
</>
|
||||
|
|
|
@ -20,16 +20,16 @@ export const ViewPicker = ({ Design, update, state }) => {
|
|||
*/
|
||||
if (state._.missingMeasurements.length > 1)
|
||||
return (
|
||||
<div className="tw-text-center tw-mt-8 tw-mb-24 tw-px-4 tw-max-w-xl tw-mx-auto">
|
||||
<div className="tw:text-center tw:mt-8 tw:mb-24 tw:px-4 tw:max-w-xl tw:mx-auto">
|
||||
<H2>Choose a view</H2>
|
||||
<div className="tw-flex tw-flex-col tw-mx-auto tw-justify-center tw-gap-2 tw-mt-4">
|
||||
<div className="tw:flex tw:flex-col tw:mx-auto tw:justify-center tw:gap-2 tw:mt-4">
|
||||
{config.measurementsFreeViews
|
||||
.filter((view) => view !== 'picker')
|
||||
.map((view) => (
|
||||
<MainCard key={view} {...{ view, update, Design }} />
|
||||
))}
|
||||
<Popout note>
|
||||
<div className="tw-text-left">
|
||||
<div className="tw:text-left">
|
||||
<H5>pe:measurementsFreeViewsOnly.t:</H5>
|
||||
<p>pe:measurementsFreeViewsOnly.d</p>
|
||||
</div>
|
||||
|
@ -39,20 +39,20 @@ export const ViewPicker = ({ Design, update, state }) => {
|
|||
)
|
||||
|
||||
return (
|
||||
<div className="tw-text-center tw-mt-8 tw-mb-24 tw-px-4">
|
||||
<div className="tw:text-center tw:mt-8 tw:mb-24 tw:px-4">
|
||||
<H2>Choose an Editor View</H2>
|
||||
<div className="tw-max-w-6xl tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-mx-auto tw-justify-center tw-gap-2 lg:tw-gap-4 tw-mt-4">
|
||||
<div className="tw:max-w-6xl tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:mx-auto tw:justify-center tw:gap-2 tw:lg:gap-4 tw:mt-4">
|
||||
{config.mainViews.map((view) => (
|
||||
<MainCard key={view} {...{ view, update, Design }} />
|
||||
))}
|
||||
</div>
|
||||
<div className="tw-max-w-6xl tw-grid tw-grid-cols-1 lg:tw-grid-cols-4 tw-mx-auto tw-justify-center tw-gap-2 lg:tw-gap-4 tw-mt-4">
|
||||
<div className="tw:max-w-6xl tw:grid tw:grid-cols-1 tw:lg:grid-cols-4 tw:mx-auto tw:justify-center tw:gap-2 tw:lg:gap-4 tw:mt-4">
|
||||
{config.extraViews.map((view) => (
|
||||
<ExtraCard key={view} {...{ view, update }} />
|
||||
))}
|
||||
</div>
|
||||
{showDev || state.ui.ux > 3 ? (
|
||||
<div className="tw-max-w-6xl tw-grid tw-grid-cols-1 lg:tw-grid-cols-4 tw-mx-auto tw-justify-center tw-gap-2 lg:tw-gap-4 tw-mt-4">
|
||||
<div className="tw:max-w-6xl tw:grid tw:grid-cols-1 tw:lg:grid-cols-4 tw:mx-auto tw:justify-center tw:gap-2 tw:lg:gap-4 tw:mt-4">
|
||||
{config.devViews.map((view) => (
|
||||
<ExtraCard key={view} {...{ view, update }} />
|
||||
))}
|
||||
|
@ -60,7 +60,7 @@ export const ViewPicker = ({ Design, update, state }) => {
|
|||
) : null}
|
||||
{state.ui.ux < 4 ? (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-ghost tw-mt-2"
|
||||
className="tw:daisy-btn tw:daisy-btn-ghost tw:mt-2"
|
||||
onClick={() => setShowDev(!showDev)}
|
||||
>
|
||||
{showDev ? 'Hide' : 'Show'} Advanced Views
|
||||
|
@ -75,19 +75,19 @@ const MainCard = ({ view, update, Design }) => {
|
|||
|
||||
return (
|
||||
<button
|
||||
className={`tw-border tw-shadow tw-p-4 tw-rounded-lg tw-w-full hover:tw-bg-secondary hover:tw-bg-opacity-20 tw-flex tw-flex-col`}
|
||||
className={`tw:border tw:shadow tw:p-4 tw:rounded-lg tw:w-full tw:hover:bg-secondary/20 tw:flex tw:flex-col`}
|
||||
title={viewLabels[view].t}
|
||||
onClick={() => update.view(view)}
|
||||
>
|
||||
<H4>
|
||||
<div
|
||||
className={`tw-flex tw-flex-row tw-items-start tw-justify-between tw-p-0 tw-mb-2 tw-text-left`}
|
||||
className={`tw:flex tw:flex-row tw:items-start tw:justify-between tw:p-0 tw:mb-2 tw:text-left`}
|
||||
>
|
||||
<span>{viewLabels[view].t}</span>
|
||||
<Icon className="tw-w-10 tw-h-10" />
|
||||
<Icon className="tw:w-10 tw:h-10" />
|
||||
</div>
|
||||
</H4>
|
||||
<p className={`tw-text-left tw-text-lg tw-m-0 tw-p-0 tw-grow-2 tw-font-medium`}>
|
||||
<p className={`tw:text-left tw:text-lg tw:m-0 tw:p-0 tw:grow-2 tw:font-medium`}>
|
||||
{viewLabels[view].d}
|
||||
</p>
|
||||
</button>
|
||||
|
@ -98,17 +98,17 @@ const ExtraCard = ({ view, update }) => {
|
|||
const Icon = viewIcons[view]
|
||||
return (
|
||||
<button
|
||||
className="tw-border tw-shadow tw-p-3 tw-rounded-lg tw-w-full hover:tw-bg-secondary hover:tw-bg-opacity-20 tw-flex tw-flex-col"
|
||||
className="tw:border tw:shadow tw:p-3 tw:rounded-lg tw:w-full tw:hover:bg-secondary/20 tw:flex tw:flex-col"
|
||||
title={viewLabels[view].t}
|
||||
onClick={() => update.view(view)}
|
||||
>
|
||||
<H5>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-p-0 tw-mb-1 tw-text-left">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-between tw:p-0 tw:mb-1 tw:text-left">
|
||||
<span>{viewLabels[view].t}</span>
|
||||
<Icon className="tw-w-8 tw-h-8" />
|
||||
<Icon className="tw:w-8 tw:h-8" />
|
||||
</div>
|
||||
</H5>
|
||||
<p className="tw-text-left tw-m-0 tw-p-0 tw-grow-2">{viewLabels[view].d}</p>
|
||||
<p className="tw:text-left tw:m-0 tw:p-0 tw:grow-2">{viewLabels[view].d}</p>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -72,13 +72,13 @@ export const View = (props) => {
|
|||
if (view === 'timing') return <TimingView {...props} />
|
||||
if (view === 'picker') return <ViewPicker {...props} />
|
||||
|
||||
return <h1 className="tw-ext-center tw-my-12">No view component for view {props.view}</h1>
|
||||
return <h1 className="tw:ext-center tw:my-12">No view component for view {props.view}</h1>
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns a view-specific icon
|
||||
*/
|
||||
export const ViewIcon = ({ view, className = 'tw-w-6 tw-h-6' }) => {
|
||||
export const ViewIcon = ({ view, className = 'tw:w-6 tw:h-6' }) => {
|
||||
const Icon = viewIcons[view] || FixmeIcon
|
||||
|
||||
return <Icon className={className} />
|
||||
|
|
|
@ -62,7 +62,7 @@ export function menuCoreSettingsSaboolHandler({ toggleSa }) {
|
|||
}
|
||||
|
||||
const CoreDocsLink = ({ item }) => (
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw-px-2`}>
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw:px-2`}>
|
||||
Learn more
|
||||
</a>
|
||||
)
|
||||
|
|
|
@ -7,7 +7,7 @@ import { linkClasses } from '@freesewing/utils'
|
|||
const DesignDocsLink = ({ design, item }) => (
|
||||
<a
|
||||
href={`/docs/designs/${design}/options/#${item.toLowerCase()}`}
|
||||
className={`${linkClasses} tw-px-2`}
|
||||
className={`${linkClasses} tw:px-2`}
|
||||
target="_BLANK"
|
||||
>
|
||||
Learn more
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from '@freesewing/react/components/Icon'
|
||||
|
||||
const UiDocsLink = ({ item }) => (
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw-px-2`}>
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw:px-2`}>
|
||||
Learn more
|
||||
</a>
|
||||
)
|
||||
|
@ -63,15 +63,15 @@ export function menuLayoutSettingsStructure(units) {
|
|||
list: ['portrait', 'landscape'],
|
||||
choiceTitles: {
|
||||
portrait: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-4">
|
||||
<PatternIcon className="tw-h-5 tw-w-5" />
|
||||
<span className="tw-grow">Portrait (tall)</span>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-4">
|
||||
<PatternIcon className="tw:h-5 tw:w-5" />
|
||||
<span className="tw:grow">Portrait (tall)</span>
|
||||
</div>
|
||||
),
|
||||
landscape: (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-4">
|
||||
<PatternIcon className="tw-h-5 tw-w-5 tw--rotate-90" />
|
||||
<span className="tw-grow">Landscape (wide)</span>
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:gap-4">
|
||||
<PatternIcon className="tw:h-5 tw:w-5 tw:-rotate-90" />
|
||||
<span className="tw:grow">Landscape (wide)</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@ import { linkClasses } from '@freesewing/utils'
|
|||
import { AsideIcon, RotateIcon, RocketIcon, UxIcon } from '@freesewing/react/components/Icon'
|
||||
|
||||
const UiDocsLink = ({ item }) => (
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw-px-2`}>
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw:px-2`}>
|
||||
Learn more
|
||||
</a>
|
||||
)
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
import React from 'react'
|
||||
|
||||
export const H1 = ({ children }) => (
|
||||
<h1 className="tw-text-5xl tw-pt-5 tw-pb-4 tw-font-thin tw-tracking-tighter lg:tw-text-6xl">
|
||||
<h1 className="tw:text-5xl tw:pt-5 tw:pb-4 tw:font-thin tw:tracking-tighter tw:lg:text-6xl">
|
||||
{children}
|
||||
</h1>
|
||||
)
|
||||
|
||||
export const H2 = ({ children }) => (
|
||||
<h2 className="tw-text-3xl tw-pt-4 tw-pb-3 tw-font-black tw-tracking-tighter tw-m-0 lg:tw-text-4xl">
|
||||
<h2 className="tw:text-3xl tw:pt-4 tw:pb-3 tw:font-black tw:tracking-tighter tw:m-0 tw:lg:text-4xl">
|
||||
{children}
|
||||
</h2>
|
||||
)
|
||||
|
||||
export const H3 = ({ children }) => (
|
||||
<h3 className="tw-text-2xl tw-pt-3 tw-pb-2 tw-font-extrabold tw-m-0 tw-tracking-tighter lg:tw-text-3xl">
|
||||
<h3 className="tw:text-2xl tw:pt-3 tw:pb-2 tw:font-extrabold tw:m-0 tw:tracking-tighter tw:lg:text-3xl">
|
||||
{children}
|
||||
</h3>
|
||||
)
|
||||
|
||||
export const H4 = ({ children }) => (
|
||||
<h4 className="tw-text-xl tw-pt-2 tw-pb-1 tw-font-bold tw-m-0 tw-tracking-tighter lg:tw-text-2xl">
|
||||
<h4 className="tw:text-xl tw:pt-2 tw:pb-1 tw:font-bold tw:m-0 tw:tracking-tighter tw:lg:text-2xl">
|
||||
{children}
|
||||
</h4>
|
||||
)
|
||||
|
||||
export const H5 = ({ children }) => (
|
||||
<h5 className="tw-text-lg tw-py-1 tw-font-semibold tw-m-0 tw-tracking-tight lg:tw-text-xl">
|
||||
<h5 className="tw:text-lg tw:py-1 tw:font-semibold tw:m-0 tw:tracking-tight tw:lg:text-xl">
|
||||
{children}
|
||||
</h5>
|
||||
)
|
||||
|
||||
export const H6 = ({ children }) => (
|
||||
<h6 className="tw-text-base tw-py-1 tw-font-medium tw-italic tw-m-0 tw-tracking-tight lg:tw-text-lg">
|
||||
<h6 className="tw:text-base tw:py-1 tw:font-medium tw:italic tw:m-0 tw:tracking-tight tw:lg:text-lg">
|
||||
{children}
|
||||
</h6>
|
||||
)
|
||||
|
|
|
@ -33,18 +33,18 @@ export const Highlight = ({
|
|||
}
|
||||
|
||||
const preProps = {
|
||||
className: `language-${language} hljs tw-text-base lg:tw-text-lg tw-whitespace-break-spaces tw-overflow-scroll tw-pr-4`,
|
||||
className: `language-${language} hljs tw:text-base tw:lg:text-lg tw:whitespace-break-spaces tw:overflow-scroll tw:pr-4`,
|
||||
}
|
||||
if (raw) preProps.dangerouslySetInnerHTML = { __html: raw }
|
||||
|
||||
const label = title ? title : defaultTitles[language] ? defaultTitles[language] : language
|
||||
|
||||
return (
|
||||
<div className="hljs tw-my-4">
|
||||
<div className="hljs tw:my-4">
|
||||
<div
|
||||
className={`
|
||||
tw-flex tw-flex-row tw-justify-between tw-items-center tw-text-xs tw-font-medium tw-text-warning
|
||||
tw-mt-1 tw-border-b tw-border-neutral-content tw-border-opacity-25 tw-px-4 tw-py-1 tw-mb-2 lg:tw-text-sm
|
||||
tw:flex tw:flex-row tw:justify-between tw:items-center tw:text-xs tw:font-medium tw:text-warning
|
||||
tw:mt-1 tw:border-b tw:border-neutral-content tw:border-opacity-25 tw:px-4 tw:py-1 tw:mb-2 tw:lg:text-sm
|
||||
`}
|
||||
>
|
||||
<span>{label}</span>
|
||||
|
|
|
@ -9,7 +9,7 @@ const page =
|
|||
* Used inside the pattern editor
|
||||
*/
|
||||
export const IconWrapper = ({
|
||||
className = 'tw-w-6 tw-h-6',
|
||||
className = 'tw:w-6 tw:h-6',
|
||||
stroke = 2,
|
||||
children = null,
|
||||
fill = false,
|
||||
|
@ -60,19 +60,19 @@ export const BeakerIcon = (props) => (
|
|||
|
||||
// Looks like a left U-turn that we slightly rotate
|
||||
export const BackIcon = (props) => (
|
||||
<IconWrapper {...props} className={`${props.className || 'tw-w-6 tw-h-6'} tw--rotate-45`}>
|
||||
<IconWrapper {...props} className={`${props.className || 'tw:w-6 tw:h-6'} tw:-rotate-45`}>
|
||||
<path d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
|
||||
</IconWrapper>
|
||||
)
|
||||
|
||||
// Looks like a red X
|
||||
export const BoolNoIcon = ({ size = 6 }) => (
|
||||
<NoIcon className={`tw-w-${size} tw-h-${size} tw-text-error`} stroke={4} />
|
||||
<NoIcon className={`tw:w-${size} tw:h-${size} tw:text-error`} stroke={4} />
|
||||
)
|
||||
|
||||
// Looks like a green checkbox
|
||||
export const BoolYesIcon = ({ size = 6 }) => (
|
||||
<OkIcon className={`tw-w-${size} tw-h-${size} tw-text-success`} stroke={4} />
|
||||
<OkIcon className={`tw:w-${size} tw:h-${size} tw:text-success`} stroke={4} />
|
||||
)
|
||||
|
||||
// Looks like a bookmark
|
||||
|
@ -258,7 +258,7 @@ export const ExportIcon = (props) => (
|
|||
|
||||
// Looks like a ! in a triangle, is intended to be shown on an error background
|
||||
export const FailureIcon = ({ size = 6 }) => (
|
||||
<NoIcon className={`tw-w-${size} tw-h-${size} tw-text-secondary-content`} stroke={4} />
|
||||
<NoIcon className={`tw:w-${size} tw:h-${size} tw:text-secondary-content`} stroke={4} />
|
||||
)
|
||||
|
||||
// Looks like a funnel
|
||||
|
@ -682,10 +682,10 @@ export const SignoutIcon = (props) => (
|
|||
export const SpinnerIcon = (props) => (
|
||||
<IconWrapper
|
||||
{...props}
|
||||
className={`${props.className ? props.className : 'tw-h-6 tw-w-6'} tw-animate-spin`}
|
||||
className={`${props.className ? props.className : 'tw:h-6 tw:w-6'} tw:animate-spin`}
|
||||
>
|
||||
<circle
|
||||
className="tw-opacity-25"
|
||||
className="tw:opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
|
@ -693,7 +693,7 @@ export const SpinnerIcon = (props) => (
|
|||
strokeWidth="4"
|
||||
></circle>
|
||||
<path
|
||||
className="tw-opacity-85"
|
||||
className="tw:opacity-85"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
|
@ -703,7 +703,7 @@ export const SpinnerIcon = (props) => (
|
|||
|
||||
// Looks like a white checkbox, intended to be shown on a success-colored background
|
||||
export const SuccessIcon = ({ size = 6 }) => (
|
||||
<OkIcon className={`tw-w-${size} tw-h-${size} tw-text-secondary-content`} stroke={4} />
|
||||
<OkIcon className={`tw:w-${size} tw:h-${size} tw:text-secondary-content`} stroke={4} />
|
||||
)
|
||||
|
||||
// Looks like the TikTok t
|
||||
|
|
|
@ -32,8 +32,8 @@ export const _Tab = ({
|
|||
setActiveTab, // Method to set the active tab
|
||||
}) => (
|
||||
<button
|
||||
className={`tw-text-lg tw-font-bold tw-capitalize tw-daisy-tab tw-daisy-tab-bordered tw-grow
|
||||
${activeTab === id ? 'tw-daisy-tab-active' : ''}`}
|
||||
className={`tw:text-lg tw:font-bold tw:capitalize tw:daisy-tab tw:daisy-tab-bordered tw:grow
|
||||
${activeTab === id ? 'tw:daisy-tab-active' : ''}`}
|
||||
onClick={() => setActiveTab(id)}
|
||||
>
|
||||
{label ? label : id}
|
||||
|
@ -52,14 +52,14 @@ const HelpLink = ({ help, Link = false }) => {
|
|||
if (typeof help === 'function')
|
||||
return (
|
||||
<button onClick={() => help} title="Show help">
|
||||
<HelpIcon className="tw-w-5 tw-h-5" />
|
||||
<HelpIcon className="tw:w-5 tw:h-5" />
|
||||
</button>
|
||||
)
|
||||
|
||||
if (typeof help === 'string')
|
||||
return (
|
||||
<Link href={help} target="_BLANK" rel="nofollow" title="Show help">
|
||||
<HelpIcon className="tw-w-5 tw-h-5" />
|
||||
<HelpIcon className="tw:w-5 tw:h-5" />
|
||||
</Link>
|
||||
)
|
||||
|
||||
|
@ -84,7 +84,7 @@ export const FormControl = ({
|
|||
const topLabelChildren = (
|
||||
<>
|
||||
{label ? (
|
||||
<span className="tw-daisy-label-text tw-text-sm lg:tw-text-base tw-font-bold tw-mb-1 tw-text-inherit tw-inline-flex tw-items-center tw-gap-1">
|
||||
<span className="tw:daisy-label-text tw:text-sm tw:lg:text-base tw:font-bold tw:mb-1 tw:text-inherit tw:inline-flex tw:items-center tw:gap-1">
|
||||
{label} <HelpLink {...{ help, Link }} />
|
||||
</span>
|
||||
) : (
|
||||
|
@ -92,33 +92,33 @@ export const FormControl = ({
|
|||
<HelpLink {...{ help, Link }} />
|
||||
</span>
|
||||
)}
|
||||
{labelTR ? <span className="tw-daisy-label-text-alt tw--mb-1">{labelTR}</span> : null}
|
||||
{labelTR ? <span className="tw:daisy-label-text-alt tw:-mb-1">{labelTR}</span> : null}
|
||||
</>
|
||||
)
|
||||
const bottomLabelChildren = (
|
||||
<>
|
||||
{labelBL ? <span className="tw-daisy-label-text-alt">{labelBL}</span> : null}
|
||||
{labelBR ? <span className="tw-daisy-label-text-alt">{labelBR}</span> : null}
|
||||
{labelBL ? <span className="tw:daisy-label-text-alt">{labelBL}</span> : null}
|
||||
{labelBR ? <span className="tw:daisy-label-text-alt">{labelBR}</span> : null}
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="tw-daisy-form-control tw-w-full tw-mt-2">
|
||||
<div className="tw:daisy-form-control tw:w-full tw:mt-2">
|
||||
{forId ? (
|
||||
<label className="tw-daisy-label tw-pb-0" htmlFor={forId}>
|
||||
<label className="tw:daisy-label tw:pb-0" htmlFor={forId}>
|
||||
{topLabelChildren}
|
||||
</label>
|
||||
) : label ? (
|
||||
<div className="tw-daisy-label tw-pb-0">{topLabelChildren}</div>
|
||||
<div className="tw:daisy-label tw:pb-0">{topLabelChildren}</div>
|
||||
) : null}
|
||||
{children}
|
||||
{labelBL || labelBR ? (
|
||||
forId ? (
|
||||
<label className="tw-daisy-label" htmlFor={forId}>
|
||||
<label className="tw:daisy-label" htmlFor={forId}>
|
||||
{bottomLabelChildren}
|
||||
</label>
|
||||
) : (
|
||||
<div className="tw-daisy-label">{bottomLabelChildren}</div>
|
||||
<div className="tw:daisy-label">{bottomLabelChildren}</div>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
|
@ -137,13 +137,13 @@ export const ButtonFrame = ({
|
|||
}) => (
|
||||
<button
|
||||
className={`
|
||||
tw-daisy-btn tw-daisy-btn-ghost tw-daisy-btn-secondary tw-h-fit
|
||||
tw-w-full ${dense ? 'tw-mt-1 tw-daisy-btn-sm tw-font-light' : 'tw-mt-2 tw-py-4 tw-h-auto tw-content-start'}
|
||||
tw-border-2 tw-border-secondary tw-text-left tw-bg-opacity-20
|
||||
${accordion ? 'hover:tw-bg-transparent' : 'hover:tw-bg-secondary hover:tw-bg-opacity-10'}
|
||||
hover:tw-border-secondary hover:tw-border-solid hover:tw-border-2
|
||||
${active ? 'tw-border-solid' : 'tw-border-dotted'}
|
||||
${active && !accordion ? 'tw-bg-secondary' : 'tw-bg-transparent'}
|
||||
tw:daisy-btn tw:daisy-btn-ghost tw:daisy-btn-secondary tw:h-fit
|
||||
tw:w-full ${dense ? 'tw:mt-1 tw:daisy-btn-sm tw:font-light' : 'tw:mt-2 tw:py-4 tw:h-auto tw:content-start'}
|
||||
tw:border-2 tw:border-secondary tw:text-left tw:bg-secondary/20
|
||||
${accordion ? 'tw:hover:bg-transparent' : 'tw:hover:bg-secondary/10'}
|
||||
tw:hover:border-secondary tw:hover:border-solid tw:hover:border-2
|
||||
${active ? 'tw:border-solid' : 'tw:border-dotted'}
|
||||
${active && !accordion ? 'tw:bg-secondary' : 'tw:bg-transparent'}
|
||||
`}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
@ -176,12 +176,12 @@ export const NumberInput = ({
|
|||
placeholder={placeholder}
|
||||
value={current}
|
||||
onChange={(evt) => update(evt.target.value)}
|
||||
className={`tw-daisy-input tw-w-full tw-daisy-input-bordered ${
|
||||
className={`tw:daisy-input tw:w-full tw:daisy-input-bordered ${
|
||||
current === original
|
||||
? 'tw-daisy-input-secondary'
|
||||
? 'tw:daisy-input-secondary'
|
||||
: valid(current)
|
||||
? 'tw-daisy-input-success'
|
||||
: 'tw-daisy-input-error'
|
||||
? 'tw:daisy-input-success'
|
||||
: 'tw:daisy-input-error'
|
||||
}`}
|
||||
{...{ max, min, step }}
|
||||
/>
|
||||
|
@ -209,12 +209,12 @@ export const StringInput = ({
|
|||
placeholder={placeholder}
|
||||
value={current}
|
||||
onChange={(evt) => update(evt.target.value)}
|
||||
className={`tw-daisy-input tw-w-full tw-daisy-input-bordered tw-text-current ${
|
||||
className={`tw:daisy-input tw:w-full tw:daisy-input-bordered tw:text-current ${
|
||||
current === original
|
||||
? 'tw-daisy-input-secondary'
|
||||
? 'tw:daisy-input-secondary'
|
||||
: valid(current)
|
||||
? 'tw-daisy-input-success'
|
||||
: 'tw-daisy-input-error'
|
||||
? 'tw:daisy-input-success'
|
||||
: 'tw:daisy-input-error'
|
||||
}`}
|
||||
/>
|
||||
</FormControl>
|
||||
|
@ -260,7 +260,7 @@ export const PasswordInput = ({
|
|||
forId={id}
|
||||
labelBR={
|
||||
<button
|
||||
className="tw-btn tw-btn-primary tw-btn-ghost tw-btn-xs tw--mt-2"
|
||||
className="tw:btn tw:btn-primary tw:btn-ghost tw:btn-xs tw:-mt-2"
|
||||
onClick={() => setReveal(!reveal)}
|
||||
>
|
||||
{reveal ? 'Hide Password' : 'Reveal Password'}
|
||||
|
@ -273,7 +273,7 @@ export const PasswordInput = ({
|
|||
placeholder={placeholder}
|
||||
value={current}
|
||||
onChange={(evt) => update(evt.target.value)}
|
||||
className={`tw-daisy-input tw-w-full tw-daisy-input-bordered ${
|
||||
className={`tw:daisy-input tw:w-full tw:daisy-input-bordered ${
|
||||
valid(current) ? 'input-success' : 'input-error'
|
||||
}`}
|
||||
{...extraProps}
|
||||
|
@ -304,12 +304,12 @@ export const EmailInput = ({
|
|||
placeholder={placeholder}
|
||||
value={current}
|
||||
onChange={(evt) => update(evt.target.value)}
|
||||
className={`tw-daisy-input tw-w-full tw-daisy-input-bordered ${
|
||||
className={`tw:daisy-input tw:w-full tw:daisy-input-bordered ${
|
||||
current === original
|
||||
? 'tw-daisy-input-secondary'
|
||||
? 'tw:daisy-input-secondary'
|
||||
: valid(current)
|
||||
? 'tw-daisy-input-success'
|
||||
: 'tw-daisy-input-error'
|
||||
? 'tw:daisy-input-success'
|
||||
: 'tw:daisy-input-error'
|
||||
}`}
|
||||
/>
|
||||
</FormControl>
|
||||
|
@ -329,7 +329,7 @@ export const DesignInput = ({
|
|||
<FormControl label={label} forId={id}>
|
||||
<select
|
||||
id={id}
|
||||
className="tw-daisy-select tw-daisy-select-bordered tw-w-full"
|
||||
className="tw:daisy-select tw:daisy-select-bordered tw:w-full"
|
||||
onChange={(evt) => update(evt.target.value)}
|
||||
value={current}
|
||||
>
|
||||
|
@ -398,7 +398,7 @@ export const ImageInput = ({
|
|||
return (
|
||||
<FormControl label={label}>
|
||||
<div
|
||||
className="tw-bg-base-100 tw-w-full tw-h-36 tw-mb-2 tw-mx-auto tw-flex tw-flex-col tw-items-center tw-text-center tw-justify-center"
|
||||
className="tw:bg-base-100 tw:w-full tw:h-36 tw:mb-2 tw:mx-auto tw:flex tw:flex-col tw:items-center tw:text-center tw:justify-center"
|
||||
style={{
|
||||
backgroundImage: `url(${
|
||||
uploadedId ? cloudflareImageUrl({ type: 'public', id: uploadedId }) : current
|
||||
|
@ -409,7 +409,7 @@ export const ImageInput = ({
|
|||
}}
|
||||
>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-neutral tw-daisy-btn-circle tw-opacity-50 hover:tw-opacity-100"
|
||||
className="tw:daisy-btn tw:daisy-btn-neutral tw:daisy-btn-circle tw:opacity-50 tw:hover:opacity-100"
|
||||
onClick={() => update(original)}
|
||||
>
|
||||
<ResetIcon />
|
||||
|
@ -423,32 +423,32 @@ export const ImageInput = ({
|
|||
<div
|
||||
{...getRootProps()}
|
||||
className={`
|
||||
tw-flex tw-rounded-lg tw-w-full tw-flex-col tw-items-center tw-justify-center
|
||||
lg:tw-p-6 lg:tw-border-4 lg:tw-border-secondary lg:tw-border-dashed
|
||||
tw:flex tw:rounded-lg tw:w-full tw:flex-col tw:items-center tw:justify-center
|
||||
tw:lg:p-6 tw:lg:border-4 tw:lg:border-secondary tw:lg:border-dashed
|
||||
`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<p className="tw-hidden lg:tw-block tw-p-0 tw-m-0">Drag and drop and image here</p>
|
||||
<p className="tw-hidden lg:tw-block tw-p-0 tw-my-2">or</p>
|
||||
<p className="tw:hidden tw:lg:block tw:p-0 tw:m-0">Drag and drop and image here</p>
|
||||
<p className="tw:hidden tw:lg:block tw:p-0 tw:my-2">or</p>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline tw-mt-4 tw-px-8`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline tw:mt-4 tw:px-8`}
|
||||
>
|
||||
Select an image to use
|
||||
</button>
|
||||
</div>
|
||||
<p className="tw-p-0 tw-my-2 tw-text-center">or</p>
|
||||
<div className="tw-flex tw-flex-row tw-items-center">
|
||||
<p className="tw:p-0 tw:my-2 tw:text-center">or</p>
|
||||
<div className="tw:flex tw:flex-row tw:items-center">
|
||||
<input
|
||||
id={id}
|
||||
type="url"
|
||||
className="tw-daisy-input tw-daisy-input-secondary tw-w-full tw-daisy-input-bordered"
|
||||
className="tw:daisy-input tw:daisy-input-secondary tw:w-full tw:daisy-input-bordered"
|
||||
placeholder="Paste an image URL here"
|
||||
value={current}
|
||||
onChange={active ? (evt) => setUrl(evt.target.value) : (evt) => update(evt.target.value)}
|
||||
/>
|
||||
{active && (
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-secondary tw-ml-2 tw-capitalize"
|
||||
className="tw:daisy-btn tw:daisy-btn-secondary tw:ml-2 tw:capitalize"
|
||||
disabled={!url || url.length < 1}
|
||||
onClick={() => upload(url, true)}
|
||||
>
|
||||
|
@ -482,10 +482,10 @@ export const ListInput = ({
|
|||
<FormControl label={label}>
|
||||
{list.map((item, i) => (
|
||||
<ButtonFrame key={i} active={item.val === current} onClick={() => update(item.val)}>
|
||||
<div className="tw-w-full tw-flex tw-flex-col tw-gap-2">
|
||||
<div className="tw-w-full tw-text-lg tw-leading-5">{item.label}</div>
|
||||
<div className="tw:w-full tw:flex tw:flex-col tw:gap-2">
|
||||
<div className="tw:w-full tw:text-lg tw:leading-5">{item.label}</div>
|
||||
{item.desc ? (
|
||||
<div className="tw-w-full tw-text-normal tw-font-normal tw-normal-case tw-pt-1 tw-leading-5">
|
||||
<div className="tw:w-full tw:text-normal tw:font-normal tw:normal-case tw:pt-1 tw:leading-5">
|
||||
{item.desc}
|
||||
</div>
|
||||
) : null}
|
||||
|
@ -514,11 +514,11 @@ export const MarkdownInput = ({
|
|||
>
|
||||
<Tabs tabs={['edit', 'preview']}>
|
||||
<Tab key="edit">
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-mt-2">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:mt-2">
|
||||
<textarea
|
||||
id={id}
|
||||
rows="5"
|
||||
className="tw-daisy-textarea tw-daisy-textarea-bordered tw-daisy-textarea-lg tw-w-full"
|
||||
className="tw:daisy-textarea tw:daisy-textarea-bordered tw:daisy-textarea-lg tw:w-full"
|
||||
value={current}
|
||||
placeholder={placeholder}
|
||||
onChange={(evt) => update(evt.target.value)}
|
||||
|
@ -580,15 +580,15 @@ export const MeasurementInput = ({
|
|||
let inputClasses = 'daisy-input-secondary'
|
||||
let bottomLeftLabel = null
|
||||
if (valid === true) {
|
||||
inputClasses = 'daisy-input-success tw-outline-success'
|
||||
inputClasses = 'daisy-input-success tw:outline-success'
|
||||
const val = `${validatedVal}${isDegree ? '°' : imperial ? '"' : 'cm'}`
|
||||
bottomLeftLabel = (
|
||||
<span className="tw-font-medium tw-text-base tw-text-success tw--mt-2 tw-block">{val}</span>
|
||||
<span className="tw:font-medium tw:text-base tw:text-success tw:-mt-2 tw:block">{val}</span>
|
||||
)
|
||||
} else if (valid === false) {
|
||||
inputClasses = 'daisy-input-error'
|
||||
bottomLeftLabel = (
|
||||
<span className="tw-font-medium tw-text-error tw-text-base tw--mt-2 tw-block">
|
||||
<span className="tw:font-medium tw:text-error tw:text-base tw:-mt-2 tw:block">
|
||||
¯\_(ツ)_/¯
|
||||
</span>
|
||||
)
|
||||
|
@ -609,7 +609,7 @@ export const MeasurementInput = ({
|
|||
labelBL={bottomLeftLabel}
|
||||
>
|
||||
<label
|
||||
className={`tw-daisy-input tw-daisy-input-bordered tw-flex tw-items-center tw-gap-2 tw-border ${inputClasses} tw-mb-1 tw-outline tw-outline-base-300 tw-bg-transparent tw-outline-2 tw-outline-offset-2`}
|
||||
className={`tw:daisy-input tw:daisy-input-bordered tw:flex tw:items-center tw:gap-2 tw:border ${inputClasses} tw:mb-1 tw:outline tw:outline-base-300 tw:bg-transparent tw:outline-2 tw:outline-offset-2`}
|
||||
>
|
||||
<input
|
||||
id={id}
|
||||
|
@ -619,12 +619,12 @@ export const MeasurementInput = ({
|
|||
placeholder={placeholder}
|
||||
value={localVal}
|
||||
onChange={(evt) => localUpdate(evt.target.value)}
|
||||
className={`tw-border-0 tw-grow-2 tw-w-full`}
|
||||
className={`tw:border-0 tw:grow-2 tw:w-full`}
|
||||
/>
|
||||
{isDegree ? '°' : imperial ? 'inch' : 'cm'}
|
||||
<label>
|
||||
<button className="tw-text-warning hover:tw-text-error" onClick={clearValue}>
|
||||
<TrashIcon className="tw-w-5 tw-h-5 tw--mb-1" />
|
||||
<button className="tw:text-warning tw:hover:text-error" onClick={clearValue}>
|
||||
<TrashIcon className="tw:w-5 tw:h-5 tw:-mb-1" />
|
||||
</button>
|
||||
</label>
|
||||
</label>
|
||||
|
@ -664,9 +664,9 @@ export const FileInput = ({
|
|||
if (current)
|
||||
return (
|
||||
<FormControl label={label} isValid={valid(current)}>
|
||||
<div className="tw-bg-base-100 tw-w-full tw-h-36 tw-mb-2 tw-mx-auto tw-flex tw-flex-col tw-items-center tw-text-center tw-justify-center">
|
||||
<div className="tw:bg-base-100 tw:w-full tw:h-36 tw:mb-2 tw:mx-auto tw:flex tw:flex-col tw:items-center tw:text-center tw:justify-center">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-neutral tw-daisy-btn-circle tw-opacity-50 hover:tw-opacity-100"
|
||||
className="tw:daisy-btn tw:daisy-btn-neutral tw:daisy-btn-circle tw:opacity-50 tw:hover:opacity-100"
|
||||
onClick={() => update(original)}
|
||||
>
|
||||
<ResetIcon />
|
||||
|
@ -683,14 +683,14 @@ export const FileInput = ({
|
|||
<div
|
||||
{...getRootProps()}
|
||||
className={`
|
||||
tw-flex tw-rounded-lg tw-w-full tw-flex-col tw-items-center tw-justify-center
|
||||
sm:tw-p-6 sm:tw-border-4 sm:tw-border-secondary sm:tw-border-dashed
|
||||
tw:flex tw:rounded-lg tw:w-full tw:flex-col tw:items-center tw:justify-center
|
||||
tw:sm:p-6 tw:sm:border-4 tw:sm:border-secondary tw:sm:border-dashed
|
||||
`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<p className="tw-hidden lg:tw-block tw-p-0 tw-m-0">Drag and drop your file here</p>
|
||||
<p className="tw:hidden tw:lg:block tw:p-0 tw:m-0">Drag and drop your file here</p>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline tw-mt-4 tw-px-8`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline tw:mt-4 tw:px-8`}
|
||||
>
|
||||
Browse...
|
||||
</button>
|
||||
|
@ -730,7 +730,7 @@ export const ToggleInput = ({
|
|||
type="checkbox"
|
||||
value={current}
|
||||
onChange={() => update(list.indexOf(current) === 0 ? list[1] : list[0])}
|
||||
className="tw-daisy-toggle tw-my-3 tw-daisy-toggle-primary"
|
||||
className="tw:daisy-toggle tw:my-3 tw:daisy-toggle-primary"
|
||||
checked={list.indexOf(current) === 0 ? true : false}
|
||||
/>
|
||||
</FormControl>
|
||||
|
|
|
@ -34,12 +34,12 @@ export const KeyVal = ({
|
|||
const inner = (
|
||||
<>
|
||||
<span
|
||||
className={`${sharedClasses} ${small ? 'tw-rounded-l' : 'tw-rounded-l-lg'} ${colorClasses1} ${small ? 'tw-text-xs' : ''} tw-pr-0.5`}
|
||||
className={`${sharedClasses} ${small ? 'tw:rounded-l' : 'tw:rounded-l-lg'} ${colorClasses1} ${small ? 'tw:text-xs' : ''} tw:pr-0.5`}
|
||||
>
|
||||
{k}
|
||||
</span>
|
||||
<span
|
||||
className={`${sharedClasses} ${small ? 'tw-rounded-r' : 'tw-rounded-r-lg'} ${colorClasses2} ${small ? 'tw-text-xs' : ''} tw-pl-0.5`}
|
||||
className={`${sharedClasses} ${small ? 'tw:rounded-r' : 'tw:rounded-r-lg'} ${colorClasses2} ${small ? 'tw:text-xs' : ''} tw:pl-0.5`}
|
||||
>
|
||||
{val}
|
||||
</span>
|
||||
|
@ -48,7 +48,7 @@ export const KeyVal = ({
|
|||
|
||||
return onClick === false ? (
|
||||
<button
|
||||
className="tw-daisy-btn-ghost tw-p-0"
|
||||
className="tw:daisy-btn-ghost tw:p-0"
|
||||
onClick={() => {
|
||||
copyToClipboard(val)
|
||||
handleCopied(setCopied, setLoadingStatus, k)
|
||||
|
@ -58,7 +58,7 @@ export const KeyVal = ({
|
|||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="tw-daisy-btn-ghost tw-p-0"
|
||||
className="tw:daisy-btn-ghost tw:p-0"
|
||||
onClick={typeof onClick === 'function' ? onClick : null}
|
||||
>
|
||||
{inner}
|
||||
|
@ -79,19 +79,19 @@ const LinkKeyVal = ({
|
|||
const inner = (
|
||||
<>
|
||||
<span
|
||||
className={`${sharedClasses} ${small ? 'tw-rounded-l' : 'tw-rounded-l-lg'} ${colorClasses1} ${small ? 'tw-text-xs' : ''} tw-pr-0.5`}
|
||||
className={`${sharedClasses} ${small ? 'tw:rounded-l' : 'tw:rounded-l-lg'} ${colorClasses1} ${small ? 'tw:text-xs' : ''} tw:pr-0.5`}
|
||||
>
|
||||
{k}
|
||||
</span>
|
||||
<span
|
||||
className={`${sharedClasses} ${small ? 'tw-rounded-r' : 'tw-rounded-r-lg'} ${colorClasses2} ${small ? 'tw-text-xs' : ''} tw-pl-0.5`}
|
||||
className={`${sharedClasses} ${small ? 'tw:rounded-r' : 'tw:rounded-r-lg'} ${colorClasses2} ${small ? 'tw:text-xs' : ''} tw:pl-0.5`}
|
||||
>
|
||||
{val}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
const linkProps = {
|
||||
className: 'tw-daisy-btn-ghost tw-p-0 hover:tw-no-underline hover:tw-bg-transparent',
|
||||
className: 'tw:daisy-btn-ghost tw:p-0 tw:hover:no-underline tw:hover:bg-transparent',
|
||||
href: href,
|
||||
}
|
||||
|
||||
|
@ -102,33 +102,33 @@ const LinkKeyVal = ({
|
|||
* If we configure the tailwind classes dynamically, they won't be picked up
|
||||
* So let's create a component for each color
|
||||
*/
|
||||
const sharedClasses = `tw-px-1 tw-text-sm tw-font-medium tw-whitespace-nowrap tw-border-2 tw-border-solid`
|
||||
const primaryClasses1 = `tw-text-primary-content tw-bg-primary tw-border-primary`
|
||||
const primaryClasses2 = `tw-text-primary tw-border-primary`
|
||||
const secondaryClasses1 = `tw-text-secondary-content tw-bg-secondary tw-border-secondary`
|
||||
const secondaryClasses2 = `tw-text-secondary tw-border-secondary`
|
||||
const neutralClasses1 = `tw-text-neutral-content tw-bg-neutral tw-border-neutral`
|
||||
const neutralClasses2 = `tw-text-neutral tw-border-neutral`
|
||||
const accentClasses1 = `tw-text-accent-content tw-bg-accent tw-border-accent`
|
||||
const accentClasses2 = `tw-text-accent tw-border-accent`
|
||||
const infoClasses1 = `tw-text-info-content tw-bg-info tw-border-info`
|
||||
const infoClasses2 = `tw-text-info tw-border-info`
|
||||
const warningClasses1 = `tw-text-warning-content tw-bg-warning tw-border-warning`
|
||||
const warningClasses2 = `tw-text-warning tw-border-warning`
|
||||
const successClasses1 = `tw-text-warning-content tw-bg-success tw-border-success`
|
||||
const successClasses2 = `tw-text-success tw-border-success`
|
||||
const errorClasses1 = `tw-text-error-content tw-bg-error tw-border-error`
|
||||
const errorClasses2 = `tw-text-error tw-border-error`
|
||||
const sharedClasses = `tw:px-1 tw:text-sm tw:font-medium tw:whitespace-nowrap tw:border-2 tw:border-solid`
|
||||
const primaryClasses1 = `tw:text-primary-content tw:bg-primary tw:border-primary`
|
||||
const primaryClasses2 = `tw:text-primary tw:border-primary`
|
||||
const secondaryClasses1 = `tw:text-secondary-content tw:bg-secondary tw:border-secondary`
|
||||
const secondaryClasses2 = `tw:text-secondary tw:border-secondary`
|
||||
const neutralClasses1 = `tw:text-neutral-content tw:bg-neutral tw:border-neutral`
|
||||
const neutralClasses2 = `tw:text-neutral tw:border-neutral`
|
||||
const accentClasses1 = `tw:text-accent-content tw:bg-accent tw:border-accent`
|
||||
const accentClasses2 = `tw:text-accent tw:border-accent`
|
||||
const infoClasses1 = `tw:text-info-content tw:bg-info tw:border-info`
|
||||
const infoClasses2 = `tw:text-info tw:border-info`
|
||||
const warningClasses1 = `tw:text-warning-content tw:bg-warning tw:border-warning`
|
||||
const warningClasses2 = `tw:text-warning tw:border-warning`
|
||||
const successClasses1 = `tw:text-warning-content tw:bg-success tw:border-success`
|
||||
const successClasses2 = `tw:text-success tw:border-success`
|
||||
const errorClasses1 = `tw:text-error-content tw:bg-error tw:border-error`
|
||||
const errorClasses2 = `tw:text-error tw:border-error`
|
||||
|
||||
const PrimarySpans = ({ small, k, val }) => (
|
||||
<>
|
||||
<span
|
||||
className={`${sharedClasses} ${small ? 'tw-rounded-l' : 'tw-rounded-l-lg'} ${primaryClasses} ${small ? 'tw-text-xs' : ''}`}
|
||||
className={`${sharedClasses} ${small ? 'tw:rounded-l' : 'tw:rounded-l-lg'} ${primaryClasses} ${small ? 'tw:text-xs' : ''}`}
|
||||
>
|
||||
{k}
|
||||
</span>
|
||||
<span
|
||||
className={`${sharedClasses} ${small ? 'tw-rounded-r' : 'tw-rounded-r-lg'} ${primaryClasses} ${small ? 'tw-text-xs' : ''}`}
|
||||
className={`${sharedClasses} ${small ? 'tw:rounded-r' : 'tw:rounded-r-lg'} ${primaryClasses} ${small ? 'tw:text-xs' : ''}`}
|
||||
>
|
||||
{val}
|
||||
</span>
|
||||
|
|
|
@ -17,10 +17,10 @@ export const Layout = ({ children = [], crumbs = [], description, Link = false,
|
|||
|
||||
return (
|
||||
<BaseLayout>
|
||||
<div className="tw-max-w-xl tw-w-full tw-mx-auto">
|
||||
<div className="tw:max-w-xl tw:w-full tw:mx-auto">
|
||||
<Breadcrumbs {...{ crumbs, title, Link }} />
|
||||
<h1 className="tw-break-words">{title}</h1>
|
||||
<div className="xl:tw-pl-4">{children}</div>
|
||||
<h1 className="tw:break-words">{title}</h1>
|
||||
<div className="tw:xl:pl-4">{children}</div>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
)
|
||||
|
@ -33,7 +33,7 @@ export const Layout = ({ children = [], crumbs = [], description, Link = false,
|
|||
* @param {array} props.children - The content to go in the layout
|
||||
*/
|
||||
export const BaseLayout = ({ children }) => (
|
||||
<div className="tw-flex tw-flex-row tw-items-start tw-w-full tw-justify-between 2xl:tw-px-36 xl:tw-px-12 tw-px-4 tw-gap-0 lg:tw-gap-4 xl:tw-gap-8 3xl:tw-gap-12">
|
||||
<div className="tw:flex tw:flex-row tw:items-start tw:w-full tw:justify-between tw:2xl:px-36 tw:xl:px-12 tw:px-4 tw:gap-0 tw:lg:gap-4 tw:xl:gap-8 3xl:tw:gap-12">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
@ -45,7 +45,7 @@ export const BaseLayout = ({ children }) => (
|
|||
* @param {array} props.children - The content to go in the layout
|
||||
*/
|
||||
export const BaseLayoutLeft = ({ children = [] }) => (
|
||||
<div className="tw-max-w-96 tw-w-1/4 tw-hidden lg:tw-block tw-shrink-0 tw-my-8 tw-sticky tw-top-4 tw-max-h-screen tw-overflow-scroll">
|
||||
<div className="tw:max-w-96 tw:w-1/4 tw:hidden tw:lg:block tw:shrink-0 tw:my-8 tw:sticky tw:top-4 tw:max-h-screen tw:overflow-scroll">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
@ -57,7 +57,7 @@ export const BaseLayoutLeft = ({ children = [] }) => (
|
|||
* @param {array} props.children - The content to go in the layout
|
||||
*/
|
||||
export const BaseLayoutRight = ({ children = [] }) => (
|
||||
<div className="tw-max-w-96 tw-w-1/4 tw-hidden xl:tw-block tw-my-8 tw-sticky tw-top-2">
|
||||
<div className="tw:max-w-96 tw:w-1/4 tw:hidden tw:xl:block tw:my-8 tw:sticky tw:top-2">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
@ -70,7 +70,7 @@ export const BaseLayoutRight = ({ children = [] }) => (
|
|||
* @param {array} props.wide - Whether or not to use the wide view
|
||||
*/
|
||||
export const BaseLayoutProse = ({ children = [], wide = false }) => (
|
||||
<div className={`tw-grow tw-w-full tw-m-auto tw-max-w-${wide ? 'full' : 'prose'} tw-my-8`}>
|
||||
<div className={`tw:grow tw:w-full tw:m-auto tw:max-w-${wide ? 'full' : 'prose'} tw:my-8`}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
@ -82,7 +82,7 @@ export const BaseLayoutProse = ({ children = [], wide = false }) => (
|
|||
* @param {array} props.children - The content to go in the layout
|
||||
*/
|
||||
export const BaseLayoutWide = ({ children = [] }) => (
|
||||
<div className="tw-grow tw-w-full tw-m-auto tw-my-8 tw-grow">{children}</div>
|
||||
<div className="tw:grow tw:w-full tw:m-auto tw:my-8 tw:grow">{children}</div>
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -94,7 +94,7 @@ export const BaseLayoutWide = ({ children = [] }) => (
|
|||
export const NoTitleLayout = ({ children }) => {
|
||||
return (
|
||||
<BaseLayout>
|
||||
<div className="tw-max-w-xl tw-w-full tw-mx-auto">
|
||||
<div className="tw:max-w-xl tw:w-full tw:mx-auto">
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
|
|
@ -38,7 +38,7 @@ export const BellaFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BellaBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -38,7 +38,7 @@ export const BentFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BentBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -38,7 +38,7 @@ export const BibiFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BibiBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -38,7 +38,7 @@ export const BobFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BobBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -40,7 +40,7 @@ export const BreannaFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BreannaBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -38,7 +38,7 @@ export const BrianFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BrianBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -40,7 +40,7 @@ export const BruceFront = ({ className, stroke = 1 }) => (
|
|||
* React component for the back
|
||||
*/
|
||||
export const BruceBack = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
stroke = 1, // Stroke width to use
|
||||
}) => {
|
||||
// Normalize stroke across designs
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react'
|
|||
* @return LineDrawing as JSX
|
||||
*/
|
||||
export const LineDrawingWrapper = ({
|
||||
className = 'tw-w-full', // CSS classes to apply
|
||||
className = 'tw:w-full', // CSS classes to apply
|
||||
viewBox = '0 0 100 100', // SVG viewBox
|
||||
stroke = 1, // Stroke to use
|
||||
children = [], // The actual linedrawing
|
||||
|
|
|
@ -54,7 +54,7 @@ export const SuccessLink = ({
|
|||
href,
|
||||
title = false,
|
||||
children,
|
||||
className = `${linkClasses} tw-text-success-content hover:tw-text-success-content`,
|
||||
className = `${linkClasses} tw:text-success-content tw:hover:text-success-content`,
|
||||
style = {},
|
||||
}) => (
|
||||
<a href={href} className={className} title={title ? title : ''} style={style}>
|
||||
|
@ -68,22 +68,22 @@ export const CardLink = ({
|
|||
icon,
|
||||
children,
|
||||
Link,
|
||||
className = 'tw-bg-base-200 tw-text-base-content',
|
||||
className = 'tw:bg-base-200 tw:text-base-content',
|
||||
}) => {
|
||||
if (!Link) Link = BaseLink
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={`tw-px-8 tw-py-10 tw-rounded-lg tw-block ${className}
|
||||
hover:tw-bg-secondary hover:tw-bg-opacity-10 tw-shadow-lg
|
||||
tw-transition-color tw-duration-300 grow hover:tw-no-underline hover:tw-text-base-content`}
|
||||
className={`tw:px-8 tw:py-10 tw:rounded-lg tw:block ${className}
|
||||
tw:hover:bg-secondary/5 tw:shadow-lg tw:bg-base-200
|
||||
tw:transition-color tw:duration-300 grow tw:hover:no-underline no-hover-decoration`}
|
||||
>
|
||||
<h2 className="tw-mb-4 tw-text-inherit tw-flex tw-flex-row tw-gap-4 tw-justify-between tw-items-center">
|
||||
{title}
|
||||
<span className="tw-shrink-0">{icon}</span>
|
||||
<h2 className="tw:mb-4 tw:text-base-content tw:flex tw:flex-row tw:gap-4 tw:justify-between tw:items-center">
|
||||
<span className="tw:text-base-content">{title}</span>
|
||||
<span className="tw:shrink-0 tw:text-base-content">{icon}</span>
|
||||
</h2>
|
||||
{children}
|
||||
<div className="tw:text-base-content">{children}</div>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,33 +2,33 @@ import React from 'react'
|
|||
import { TipIcon, ChatIcon, WarningIcon } from '@freesewing/react/components/Icon'
|
||||
|
||||
export const MiniTip = ({ children }) => (
|
||||
<div className="tw-flex tw-flex-row tw-border tw-border-success tw-rounded">
|
||||
<div className="tw-bg-success tw-text-success-content tw-p-1 tw-rounded-l tw-flex tw-flex-row tw-items-center">
|
||||
<TipIcon className="tw-w-6 tw-h-6 tw-text-success-content" />
|
||||
<div className="tw:flex tw:flex-row tw:border tw:border-success tw:rounded">
|
||||
<div className="tw:bg-success tw:text-success-content tw:p-1 tw:rounded-l tw:flex tw:flex-row tw:items-center">
|
||||
<TipIcon className="tw:w-6 tw:h-6 tw:text-success-content" />
|
||||
</div>
|
||||
<div className="tw-p-1 tw-px-2 tw-text-sm tw-font-medium tw-bg-success/10 tw-grow tw-rounded-r">
|
||||
<div className="tw:p-1 tw:px-2 tw:text-sm tw:font-medium tw:bg-success/10 tw:grow tw:rounded-r">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const MiniNote = ({ children }) => (
|
||||
<div className="tw-flex tw-flex-row tw-border tw-border-info tw-rounded">
|
||||
<div className="tw-bg-info tw-text-info-content tw-p-1 tw-rounded-l tw-flex tw-flex-row tw-items-center">
|
||||
<ChatIcon className="tw-w-6 tw-h-6 tw-text-info-content" />
|
||||
<div className="tw:flex tw:flex-row tw:border tw:border-info tw:rounded">
|
||||
<div className="tw:bg-info tw:text-info-content tw:p-1 tw:rounded-l tw:flex tw:flex-row tw:items-center">
|
||||
<ChatIcon className="tw:w-6 tw:h-6 tw:text-info-content" />
|
||||
</div>
|
||||
<div className="tw-p-1 tw-px-2 tw-text-sm tw-font-medium tw-bg-info/10 tw-grow tw-rounded-r">
|
||||
<div className="tw:p-1 tw:px-2 tw:text-sm tw:font-medium tw:bg-info/10 tw:grow tw:rounded-r">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const MiniWarning = ({ children }) => (
|
||||
<div className="tw-flex tw-flex-row tw-border tw-border-warning tw-rounded">
|
||||
<div className="tw-bg-warning tw-text-warning-content tw-p-1 tw-rounded-l tw-flex tw-flex-row tw-items-center">
|
||||
<WarningIcon className="tw-w-6 tw-h-6 tw-text-warning-content" />
|
||||
<div className="tw:flex tw:flex-row tw:border tw:border-warning tw:rounded">
|
||||
<div className="tw:bg-warning tw:text-warning-content tw:p-1 tw:rounded-l tw:flex tw:flex-row tw:items-center">
|
||||
<WarningIcon className="tw:w-6 tw:h-6 tw:text-warning-content" />
|
||||
</div>
|
||||
<div className="tw-p-1 tw-px-2 tw-text-sm tw-font-medium tw-bg-warning/10 tw-grow tw-rounded-r">
|
||||
<div className="tw:p-1 tw:px-2 tw:text-sm tw:font-medium tw:bg-warning/10 tw:grow tw:rounded-r">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,10 +3,10 @@ import { ModalContext } from '@freesewing/react/context/Modal'
|
|||
import { CloseIcon } from '@freesewing/react/components/Icon'
|
||||
|
||||
const slideClasses = {
|
||||
left: 'tw--translate-x-full',
|
||||
right: 'tw-translate-x-full',
|
||||
top: 'tw--translate-y-full',
|
||||
bottom: 'tw-translate-y-full',
|
||||
left: 'tw:-translate-x-full',
|
||||
right: 'tw:translate-x-full',
|
||||
top: 'tw:-translate-y-full',
|
||||
bottom: 'tw:translate-y-full',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,8 +29,8 @@ export const ModalWrapper = ({
|
|||
flex = 'row',
|
||||
justify = 'center',
|
||||
items = 'center',
|
||||
bg = 'neutral lg:tw-neutral',
|
||||
bgOpacity = '100 lg:tw-bg-opacity-70',
|
||||
bg = 'neutral',
|
||||
bgOpacity = '70',
|
||||
bare = false,
|
||||
keepOpenOnClick = false,
|
||||
slideFrom = 'left',
|
||||
|
@ -53,8 +53,8 @@ export const ModalWrapper = ({
|
|||
|
||||
// CSS classes for animation
|
||||
const animation = animate
|
||||
? `lg:tw-opacity-0 ${slideClasses[slideFrom]} lg:tw-translate-x-0 lg:tw-translate-y-0`
|
||||
: 'tw-opacity-100 tw-translate-none'
|
||||
? `tw:lg:opacity-0 ${slideClasses[slideFrom]} tw:lg:translate-x-0 tw:lg:translate-y-0`
|
||||
: 'tw:opacity-100 tw:translate-none'
|
||||
|
||||
const stopClick = (evt) => {
|
||||
/*
|
||||
|
@ -66,10 +66,10 @@ export const ModalWrapper = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`tw-fixed tw-top-0 tw-left-0 tw-m-0 tw-p-0 tw-shadow tw-w-full tw-h-screen
|
||||
tw-transform-all tw-duration-150 ${animation}
|
||||
tw-bg-${bg} tw-bg-opacity-${bgOpacity} hover:tw-cursor-pointer
|
||||
tw-flex tw-flex-${flex} tw-justify-${justify} tw-items-${items} lg:tw-p-12 tw-backdrop-blur-md`}
|
||||
className={`tw:fixed tw:top-0 tw:left-0 tw:m-0 tw:p-0 tw:shadow tw:w-full tw:h-screen
|
||||
tw:transform-all tw:duration-150 ${animation}
|
||||
tw:bg-${bg}/${bgOpacity} tw:hover:cursor-pointer
|
||||
tw:flex tw:flex-${flex} tw:justify-${justify} tw:items-${items} tw:lg:p-12 tw:backdrop-blur-md`}
|
||||
onClick={close}
|
||||
style={{ zIndex: 250 }}
|
||||
>
|
||||
|
@ -78,16 +78,16 @@ export const ModalWrapper = ({
|
|||
) : (
|
||||
<div
|
||||
onClick={keepOpenOnClick ? stopClick : null}
|
||||
className={`tw-z-30 tw-bg-base-100 tw-p-4 lg:tw-px-8 lg:tw-rounded-lg lg:tw-shadow-lg tw-max-h-full tw-overflow-auto hover:tw-cursor-default ${
|
||||
fullWidth ? 'tw-w-full' : ''
|
||||
className={`tw:z-30 tw:bg-base-100 tw:p-4 tw:lg:px-8 tw:lg:rounded-lg tw:lg:shadow-lg tw:max-h-full tw:overflow-auto tw:hover:cursor-default ${
|
||||
fullWidth ? 'tw:w-full' : ''
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
<button
|
||||
className="tw-fixed tw-bottom-2 tw-right-2 tw-daisy-btn tw-daisy-btn-neutral tw-daisy-btn-circle lg:tw-hidden"
|
||||
className="tw:fixed tw:bottom-2 tw:right-2 tw:daisy-btn tw:daisy-btn-neutral tw:daisy-btn-circle tw:lg:hidden"
|
||||
onClick={close}
|
||||
>
|
||||
<CloseIcon className="tw-w-8 tw-h-8" />
|
||||
<CloseIcon className="tw:w-8 tw:h-8" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -16,19 +16,19 @@ const NewLink = ({ title, Icon, description, href, Link }) => {
|
|||
const linkProps = {
|
||||
href,
|
||||
className:
|
||||
'tw-p-8 tw--ml-4 tw--mr-4 md:tw-m-0 tw-rounded-none md:tw-rounded-xl ' +
|
||||
'md:tw-shadow hover:tw-bg-secondary tw-bg-base-200 hover:tw-bg-opacity-10 ' +
|
||||
'tw-w-full tw-max-w-lg hover:tw-no-underline',
|
||||
'tw:p-8 tw:-ml-4 tw:-mr-4 tw:md:m-0 tw:rounded-none tw:md:rounded-xl ' +
|
||||
'tw:md:shadow tw:hover:bg-secondary/10 tw:bg-base-200/10 ' +
|
||||
'tw:w-full tw:max-w-lg tw:hover:no-underline',
|
||||
}
|
||||
|
||||
const inner = (
|
||||
<>
|
||||
<h4 className="tw-flex tw-flex-row tw-items-start tw-justify-between tw-w-full tw-m-0 tw-p-0 tw-text-inherit">
|
||||
<h4 className="tw:flex tw:flex-row tw:items-start tw:justify-between tw:w-full tw:m-0 tw:p-0 tw:text-inherit">
|
||||
<span>{title}</span>
|
||||
<Icon className="tw-w-12 tw-h-12 tw--mt-2" stroke={1.5} />
|
||||
<Icon className="tw:w-12 tw:h-12 tw:-mt-2" stroke={1.5} />
|
||||
</h4>
|
||||
<div
|
||||
className={`tw-normal-case tw-text-base tw-font-medium tw-text-left tw-pt-2 tw-text-inherit`}
|
||||
className={`tw:normal-case tw:text-base tw:font-medium tw:text-left tw:pt-2 tw:text-inherit`}
|
||||
>
|
||||
{description}
|
||||
</div>
|
||||
|
@ -81,8 +81,8 @@ export const NewLinks = ({ Link = false }) => {
|
|||
const { account } = useAccount()
|
||||
|
||||
return (
|
||||
<div className="tw-w-full tw-max-w-7xl">
|
||||
<div className="tw-grid tw-grid-cols-1 xl:tw-grid-cols-2 tw-gap-4 tw-mb-8">
|
||||
<div className="tw:w-full tw:max-w-7xl">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:xl:grid-cols-2 tw:gap-4 tw:mb-8">
|
||||
{Object.entries(newLinks).map(([href, link]) => (
|
||||
<NewLink key={href} href={href} {...link} />
|
||||
))}
|
||||
|
|
|
@ -51,7 +51,7 @@ export const NewsletterSignup = ({ Link = false, noP = false, noTitle = false, n
|
|||
return (
|
||||
<div
|
||||
className={
|
||||
noBox ? '' : 'tw-w-full tw-shadow tw-border tw-rounded-lg tw-p-4 tw-bg-secondary/5'
|
||||
noBox ? '' : 'tw:w-full tw:shadow tw:border tw:rounded-lg tw:p-4 tw:bg-secondary/5'
|
||||
}
|
||||
>
|
||||
{subscribed ? (
|
||||
|
@ -60,8 +60,8 @@ export const NewsletterSignup = ({ Link = false, noP = false, noTitle = false, n
|
|||
<p>
|
||||
We have sent and email to <b>{email}</b> with a link to confirm this action.
|
||||
</p>
|
||||
<div className="tw-ml-2 tw-pl-2 tw-border-l-4 tw-border-secondary/20">
|
||||
<h6 className="tw-mt-2 tw-pb-0">Why do I need to confirm this?</h6>
|
||||
<div className="tw:ml-2 tw:pl-2 tw:border-l-4 tw:border-secondary/20">
|
||||
<h6 className="tw:mt-2 tw:pb-0">Why do I need to confirm this?</h6>
|
||||
<small>
|
||||
Without this confirmation step, anyone could attempt to {unsubscribe ? 'un' : ''}
|
||||
subcribe this E-mail address {unsubscribe ? 'from' : 'to'} our newsletter.
|
||||
|
@ -89,15 +89,15 @@ export const NewsletterSignup = ({ Link = false, noP = false, noTitle = false, n
|
|||
</>
|
||||
}
|
||||
labelBL={
|
||||
<span className="tw-flex tw-flex-row tw-items-center tw-flex-wrap tw-gap-1">
|
||||
<span className="tw:flex tw:flex-row tw:items-center tw:flex-wrap tw:gap-1">
|
||||
{validateEmail(email) ? (
|
||||
<>
|
||||
<OkIcon className="tw-text-success tw-w-5 tw-h-5" stroke={3} />
|
||||
<OkIcon className="tw:text-success tw:w-5 tw:h-5" stroke={3} />
|
||||
Looks great, click below to {unsubscribe ? 'un' : ''}subscribe this address
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<WarningIcon className="tw-text-error tw-w-5 tw-h-5" /> Please enter a valid
|
||||
<WarningIcon className="tw:text-error tw:w-5 tw:h-5" /> Please enter a valid
|
||||
E-mail address
|
||||
</>
|
||||
)}
|
||||
|
@ -108,7 +108,7 @@ export const NewsletterSignup = ({ Link = false, noP = false, noTitle = false, n
|
|||
valid={validateEmail}
|
||||
/>
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-w-full"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:w-full"
|
||||
disabled={!validateEmail(email)}
|
||||
onClick={subscribe}
|
||||
>
|
||||
|
@ -174,7 +174,7 @@ export const NewsletterUnsubscribe = ({ Link = false }) => {
|
|||
</p>
|
||||
<button
|
||||
onClick={unsubscribe}
|
||||
className="tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-large tw-w-full tw-my-4"
|
||||
className="tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-large tw:w-full tw:my-4"
|
||||
>
|
||||
Unsubscribe
|
||||
</button>
|
||||
|
|
|
@ -6,13 +6,13 @@ import { useAccount } from '@freesewing/react/hooks/useAccount'
|
|||
|
||||
export const PleaseSubscribe = (props = {}) => (
|
||||
<div
|
||||
className={`tw-max-w-7xl tw-m-auto tw-px-0 tw--mt-12 tw-mb-24 ${props.dense ? '' : 'md:tw-my-24'}`}
|
||||
className={`tw:max-w-7xl tw:m-auto tw:px-0 tw:-mt-12 tw:mb-24 ${props.dense ? '' : 'tw:md:my-24'}`}
|
||||
>
|
||||
<div className="tw-p-1 tw-bg-gradient-to-tr tw-from-neutral tw-to-primary tw-mt-12 tw-rounded-none md:tw-rounded-lg lg:tw-rounded-xl md:tw-shadow tw-text-neutral-content tw-p-8 lg:tw-px-12 md:tw-py-0">
|
||||
<div className="tw-flex tw-flex-col md:tw-gap-2 lg:tw-gap-12 md:tw-grid md:tw-grid-cols-2">
|
||||
<div className="tw:p-1 tw:bg-linear-to-tr tw:from-neutral tw:to-primary tw:mt-12 tw:rounded-none tw:md:rounded-lg tw:lg:rounded-xl tw:md:shadow tw:text-neutral-content tw:p-8 tw:lg:px-12 tw:md:py-0">
|
||||
<div className="tw:flex tw:flex-col tw:md:gap-2 tw:lg:gap-12 tw:md:grid tw:md:grid-cols-2">
|
||||
<Plea />
|
||||
<div className="tw--mt-8 md:tw-mt-0 tw-pt-0 md:tw-pt-8 tw-pb-8 lg:tw-py-12 tw-max-w-prose tw-m-auto tw-w-full tw-m-auto">
|
||||
<h2 className="tw-text-inherit">Support FreeSewing</h2>
|
||||
<div className="tw:-mt-8 tw:md:mt-0 tw:pt-0 tw:md:pt-8 tw:pb-8 tw:lg:py-12 tw:max-w-prose tw:m-auto tw:w-full tw:m-auto">
|
||||
<h2 className="tw:text-inherit">Support FreeSewing</h2>
|
||||
<Subscribe {...props} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,8 +21,8 @@ export const PleaseSubscribe = (props = {}) => (
|
|||
)
|
||||
|
||||
export const Plea = () => (
|
||||
<div className="md:tw-pt-8 tw-pb-8 lg:tw-py-12 tw-max-w-prose tw-w-full tw-m-auto">
|
||||
<h2 className="tw-text-inherit tw-mb-4">
|
||||
<div className="tw:md:pt-8 tw:pb-8 tw:lg:py-12 tw:max-w-prose tw:w-full tw:m-auto">
|
||||
<h2 className="tw:text-inherit tw:mb-4">
|
||||
Hi friend
|
||||
<span role="img"> 👋</span>
|
||||
</h2>
|
||||
|
@ -33,11 +33,11 @@ export const Plea = () => (
|
|||
'Thanks in advance for considering it.',
|
||||
'love',
|
||||
].map((txt, i) => (
|
||||
<p className="tw-text-inherit tw-font-medium tw-mb-2" key={i}>
|
||||
<p className="tw:text-inherit tw:font-medium tw:mb-2" key={i}>
|
||||
{txt}
|
||||
</p>
|
||||
))}
|
||||
<Joost className="tw-ml-12 tw--mt-8 tw-w-32" />
|
||||
<Joost className="tw:ml-12 tw:-mt-8 tw:w-32" />
|
||||
</div>
|
||||
)
|
||||
|
||||
|
@ -87,28 +87,28 @@ export const Subscribe = ({
|
|||
: paypalConfig.periods
|
||||
|
||||
return (
|
||||
<div className="tw-w-full">
|
||||
<div className="tw-flex tw-flex-row tw-gap-2">
|
||||
<div className="tw-daisy-form-control tw-w-full">
|
||||
<label className="tw-daisy-label">
|
||||
<span className="tw-daisy-label-text-alt tw-text-inherit">Your Contribution</span>
|
||||
<div className="tw:w-full">
|
||||
<div className="tw:flex tw:flex-row tw:gap-2">
|
||||
<div className="tw:daisy-form-control tw:w-full">
|
||||
<label className="tw:daisy-label">
|
||||
<span className="tw:daisy-label-text-alt tw:text-inherit">Your Contribution</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
inputMode="decimal"
|
||||
placeholder="Enter amount here"
|
||||
pattern="[0-9]+([.][0-9]+)?"
|
||||
className="tw-daisy-input tw-daisy-input-bordered tw-w-full tw-text-base-content"
|
||||
className="tw:daisy-input tw:daisy-input-bordered tw:w-full tw:text-base-content"
|
||||
value={amount}
|
||||
onChange={(evt) => setAmount(evt.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-form-control tw-w-24">
|
||||
<label className="tw-daisy-label">
|
||||
<span className="tw-daisy-label-text-alt tw-text-inherit">Currency</span>
|
||||
<div className="tw:form-control tw:w-24">
|
||||
<label className="tw:daisy-label">
|
||||
<span className="tw:daisy-label-text-alt tw:text-inherit">Currency</span>
|
||||
</label>
|
||||
<select
|
||||
className="tw-daisy-select tw-daisy-select-bordered tw-text-base-content"
|
||||
className="tw:daisy-select tw:daisy-select-bordered tw:text-base-content"
|
||||
defaultValue={currency}
|
||||
onChange={(evt) => setCurrency(evt.target.value)}
|
||||
>
|
||||
|
@ -121,13 +121,13 @@ export const Subscribe = ({
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="tw-daisy-label">
|
||||
<div className="tw-daisy-label-text-alt tw-text-inherit tw-flex tw-flex-row tw-flex-wrap tw-gap-1">
|
||||
<span className="tw-hidden lg:tw-inline">Presets:</span>
|
||||
<label className="tw:daisy-label">
|
||||
<div className="tw:daisy-label-text-alt tw:text-inherit tw:flex tw:flex-row tw:flex-wrap tw:gap-1">
|
||||
<span className="tw:hidden tw:lg:inline">Presets:</span>
|
||||
{amounts.map((val) => (
|
||||
<button
|
||||
key={val}
|
||||
className="tw-font-bold tw-underline tw-decoration-2 tw-px-1 hover:tw-decoration-4"
|
||||
className="tw:font-bold tw:underline tw:decoration-2 tw:px-1 tw:hover:decoration-4"
|
||||
onClick={() => setAmount(val)}
|
||||
>
|
||||
{val}
|
||||
|
@ -136,26 +136,26 @@ export const Subscribe = ({
|
|||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div className="tw-grid tw-grid-cols-2 md:tw-grid-cols-3 tw-gap-2 tw-mt-2">
|
||||
<div className="tw:grid tw:grid-cols-2 tw:md:grid-cols-3 tw:gap-2 tw:mt-2">
|
||||
{periods.map((val) => (
|
||||
<div
|
||||
className={`tw-daisy-form-control tw-border tw-border-solid tw-border-inherit tw-rounded tw-px-1 tw-flex tw-flex-col tw-justify-center ${
|
||||
period === val ? 'tw-bg-base-100 tw-text-base-content' : ''
|
||||
className={`tw:daisy-form-control tw:border tw:border-solid tw:border-inherit tw:rounded tw:px-1 tw:flex tw:flex-col tw:justify-center ${
|
||||
period === val ? 'tw:bg-base-100 tw:text-base-content' : ''
|
||||
}`}
|
||||
key={val}
|
||||
>
|
||||
<label className="tw-daisy-label tw-cursor-pointer tw-py-1.5 tw-flex tw-flex-row tw-gap-2 tw-items-center tw-overflow-clip tw-justify-start">
|
||||
<label className="tw:daisy-label tw:cursor-pointer tw:py-1.5 tw:flex tw:flex-row tw:gap-2 tw:items-center tw:overflow-clip tw:justify-start">
|
||||
<input
|
||||
type="radio"
|
||||
name="period"
|
||||
className={`tw-daisy-radio checked:tw-bg-${color} tw-border-${color} tw-daisy-radio-xs lg:tw-daisy-radio-sm tw-bg-secondary/20`}
|
||||
className={`tw:daisy-radio checked:tw:bg-${color} tw:border-${color} tw:daisy-radio-xs lg:tw:daisy-radio-sm tw:bg-secondary/20`}
|
||||
value={val}
|
||||
onChange={() => setPeriod(val)}
|
||||
checked={val === period ? 1 : 0}
|
||||
/>
|
||||
<span
|
||||
className={`tw-daisy-label-text tw-text-inherit tw-text-xs lg:tw-text-sm ${
|
||||
val === period ? 'tw-font-bold' : ''
|
||||
className={`tw:daisy-label-text tw:text-inherit tw:text-xs tw:lg:text-sm ${
|
||||
val === period ? 'tw:font-bold' : ''
|
||||
}`}
|
||||
>
|
||||
{paypalConfig.periodLabels[val]}
|
||||
|
@ -173,16 +173,16 @@ export const Subscribe = ({
|
|||
>
|
||||
<PaypalFormBody {...{ currency, amount, period }} />
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-${color} tw-w-full tw-mt-4`}
|
||||
className={`tw:daisy-btn tw:daisy-btn-${color} tw:w-full tw:mt-4`}
|
||||
disabled={!(Number(amount) > 0)}
|
||||
type="submit"
|
||||
>
|
||||
{period === 'x' ? 'Donate' : 'Subscribe'}
|
||||
</button>
|
||||
<p className="tw-text-center tw-text-sm tw-text-neutral-content tw-mt-2 tw-opacity-80">
|
||||
<p className="tw:text-center tw:text-sm tw:text-neutral-content tw:mt-2 tw:opacity-80">
|
||||
Don't have a PayPal account?
|
||||
<a href="https://ko-fi.com/freesewing" target="_BLANK" className={linkClasses}>
|
||||
<b className="tw-text-neutral-content tw-pl-2">Ko-fi.com/FreeSewing</b>
|
||||
<b className="tw:text-neutral-content tw:pl-2">Ko-fi.com/FreeSewing</b>
|
||||
</a>
|
||||
</p>
|
||||
</form>
|
||||
|
@ -190,7 +190,7 @@ export const Subscribe = ({
|
|||
)
|
||||
}
|
||||
|
||||
export const Joost = ({ className = 'tw-w-32', stroke = 0 }) => (
|
||||
export const Joost = ({ className = 'tw:w-32', stroke = 0 }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
|
|
|
@ -44,22 +44,22 @@ export const Popout = (props) => {
|
|||
|
||||
return props.compact ? (
|
||||
<div
|
||||
className={`tw-relative ${
|
||||
props.dense ? 'tw-my-1' : 'tw-my-8'
|
||||
} tw-bg-${color} tw-bg-opacity-5 tw--ml-4 tw--mr-4 sm:tw-ml-0 sm:tw-mr-0 ${className}`}
|
||||
className={`tw:relative ${
|
||||
props.dense ? 'tw:my-1' : 'tw:my-8'
|
||||
} tw:bg-${color}/5 tw:-ml-4 tw:-mr-4 tw:sm:ml-0 tw:sm:mr-0 ${className}`}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
tw-border-y-4 sm:tw-border-0 sm:tw-border-l-4 tw-px-4
|
||||
tw-shadow tw-text-base border-${color}
|
||||
tw-flex tw-flex-row tw-items-center
|
||||
tw:border-y-4 tw:sm:border-0 tw:sm:border-l-4 tw:px-4
|
||||
tw:shadow tw:text-base border-${color}
|
||||
tw:flex tw:flex-row tw:items-center
|
||||
`}
|
||||
>
|
||||
<div className={`tw-font-bold tw-uppercase tw-text-${color}`}>
|
||||
<div className={`tw:font-bold tw:uppercase tw:text-${color}`}>
|
||||
{props.title || (
|
||||
<>
|
||||
<span>{type.toUpperCase()}</span>
|
||||
<span className="tw-px-3">|</span>
|
||||
<span className="tw:px-3">|</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -68,23 +68,23 @@ export const Popout = (props) => {
|
|||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={`tw-relative tw-my-8 tw-bg-${color} tw-bg-opacity-5 tw--ml-4 tw--mr-4 sm:tw-ml-0 sm:tw-mr-0 ${className}`}
|
||||
className={`tw:relative tw:my-8 tw:bg-${color}/5 tw:-ml-4 tw:-mr-4 tw:sm:ml-0 tw:sm:mr-0 ${className}`}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
tw-border-y-4 tw-border-x-0 sm:tw-border-0 sm:tw-border-l-4 tw-px-6 sm:tw-px-8 tw-py-4 sm:tw-py-2
|
||||
tw-shadow tw-text-base tw-border-${color} tw-border-solid
|
||||
tw:border-y-4 tw:border-x-0 tw:sm:border-0 tw:sm:border-l-4 tw:px-6 tw:sm:px-8 tw:py-4 tw:sm:py-2
|
||||
tw:shadow tw:text-base tw:border-${color} tw:border-solid
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`tw-font-bold tw-flex tw-flex-row tw-gap-1 tw-items-end tw-justify-between`}
|
||||
className={`tw:font-bold tw:flex tw:flex-row tw:gap-1 tw:items-end tw:justify-between`}
|
||||
>
|
||||
<div>
|
||||
<span className={`tw-font-bold tw-uppercase tw-text-${color}`}>
|
||||
<span className={`tw:font-bold tw:uppercase tw:text-${color}`}>
|
||||
{props.title ? props.title : type === 'tldr' ? 'TL;DR' : type.toUpperCase()}
|
||||
</span>
|
||||
<span className={`tw-font-normal tw-text-base text-${color}`}>
|
||||
{type === 'tw-comment' && (
|
||||
<span className={`tw:font-normal tw:text-base text-${color}`}>
|
||||
{type === 'tw:comment' && (
|
||||
<>
|
||||
{' '}
|
||||
by <b>{props.by}</b>
|
||||
|
@ -93,14 +93,14 @@ export const Popout = (props) => {
|
|||
</span>
|
||||
</div>
|
||||
{props.hideable && (
|
||||
<button onClick={() => setHide(true)} className="hover:tw-text-secondary" title="Close">
|
||||
<button onClick={() => setHide(true)} className="tw:hover:text-secondary" title="Close">
|
||||
<CloseIcon />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="tw-py-1 first:tw-mt-0 tw-popout-content">{props.children}</div>
|
||||
<div className="tw:py-1 tw:first:mt-0 tw:popout-content">{props.children}</div>
|
||||
{type === 'comment' && (
|
||||
<div className={`tw-font-bold tw-italic text-${color}`}>{props.by}</div>
|
||||
<div className={`tw:font-bold tw:italic text-${color}`}>{props.by}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -69,14 +69,14 @@ export const UserProfile = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-w-full tw-flex tw-flex-row tw-flex-wrap tw-items-center tw-gap-4">
|
||||
<div className="tw:w-full tw:flex tw:flex-row tw:flex-wrap tw:items-center tw:gap-4">
|
||||
<Avatar ihash={data.ihash} />
|
||||
<div className="tw-flex tw-flex-col tw-items-start tw-gap-1">
|
||||
<div className="tw:flex tw:flex-col tw:items-start tw:gap-1">
|
||||
<h2>{data.username}</h2>
|
||||
<KeyVal k="role" val={data.role} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-my-4 tw-border-l-4 tw-pl-2">
|
||||
<div className="tw:my-4 tw:border-l-4 tw:pl-2">
|
||||
<b>Permalink: </b>
|
||||
<Link href={`/users?id=${ruid}`}>{`freesewing.eu/users?id=${ruid}`}</Link>
|
||||
</div>
|
||||
|
@ -100,7 +100,7 @@ export const Avatar = ({ ihash }) => {
|
|||
<ModalWrapper>
|
||||
<img
|
||||
src={cloudflareImageUrl({ id: `uid-${ihash}`, variant: 'public' })}
|
||||
className="tw-max-w-full tw-max-h-screen"
|
||||
className="tw:max-w-full tw:max-h-screen"
|
||||
/>
|
||||
</ModalWrapper>
|
||||
)
|
||||
|
@ -108,7 +108,7 @@ export const Avatar = ({ ihash }) => {
|
|||
>
|
||||
<img
|
||||
src={cloudflareImageUrl({ id: `uid-${ihash}`, variant: 'sq500' })}
|
||||
className="tw-w-32 tw-h-32 tw-rounded-full tw-shadow tw-border-current tw-border-4"
|
||||
className="tw:w-32 tw:h-32 tw:rounded-full tw:shadow tw:border-current tw:border-4"
|
||||
/>
|
||||
</button>
|
||||
)
|
||||
|
|
|
@ -15,15 +15,15 @@ import { H1, H2, H3 } from '@freesewing/react/components/Heading'
|
|||
const ConsentForm = () => null
|
||||
|
||||
const Wrap = ({ children }) => (
|
||||
<div className="tw-m-auto tw-max-w-xl tw-text-center tw-mt-8 tw-p-8">{children}</div>
|
||||
<div className="tw:m-auto tw:max-w-xl tw:text-center tw:mt-8 tw:p-8">{children}</div>
|
||||
)
|
||||
|
||||
const ContactSupport = ({ Link = false }) => {
|
||||
if (!Link) Link = DefaultLink
|
||||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-center tw-gap-4 tw-mt-8">
|
||||
<Link href="/support" className="tw-daisy-btn tw-daisy-btn-success tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-center tw:gap-4 tw:mt-8">
|
||||
<Link href="/support" className="tw:daisy-btn tw:daisy-btn-success tw:w-full">
|
||||
Contact Support
|
||||
</Link>
|
||||
</div>
|
||||
|
@ -38,17 +38,17 @@ const AuthRequired = ({ Link, banner }) => {
|
|||
{banner}
|
||||
<H3>Authentication Required</H3>
|
||||
<p>This functionality requires a FreeSewing account</p>
|
||||
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-8">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:md:grid-cols-2 tw:gap-2 tw:mt-8">
|
||||
<Link
|
||||
href="/signup"
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-secondary tw-w-full`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-secondary tw:w-full`}
|
||||
>
|
||||
<PlusIcon />
|
||||
Sign Up
|
||||
</Link>
|
||||
<Link
|
||||
href="/signin"
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-secondary tw-daisy-btn-outline tw-w-full`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline tw:w-full`}
|
||||
>
|
||||
<LockIcon />
|
||||
Sign In
|
||||
|
@ -67,8 +67,8 @@ const AccountInactive = ({ Link, banner }) => {
|
|||
<H3>Account Inactive</H3>
|
||||
<p>You must activate your account via the signup link we sent you.</p>
|
||||
<p>If you cannot find the link, you can receive a new one by signing up again.</p>
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-center tw-gap-4 tw-mt-8">
|
||||
<Link href="/signup" className="tw-daisy-btn tw-daisy-btn-primary tw-w-full">
|
||||
<div className="tw:flex tw:flex-row tw:items-center tw:justify-center tw:gap-4 tw:mt-8">
|
||||
<Link href="/signup" className="tw:daisy-btn tw:daisy-btn-primary tw:w-full">
|
||||
Sign Up
|
||||
</Link>
|
||||
</div>
|
||||
|
@ -142,7 +142,7 @@ const ConsentLacking = ({ banner, refresh }) => {
|
|||
|
||||
return (
|
||||
<Wrap>
|
||||
<div className="tw-text-left">
|
||||
<div className="tw:text-left">
|
||||
{banner}
|
||||
<ConsentForm submit={updateConsent} />
|
||||
</div>
|
||||
|
@ -204,11 +204,11 @@ export const RoleBlock = ({ children, user = false, Link = false }) => {
|
|||
if (!ready) return <Spinner />
|
||||
|
||||
const banner = impersonating ? (
|
||||
<div className="tw-bg-warning tw-rounded-lg tw-shadow tw-py-4 tw-px-6 tw-flex tw-flex-row tw-items-center tw-gap-4 tw-justify-between">
|
||||
<span className="tw-text-base-100 tw-text-left">
|
||||
<div className="tw:bg-warning tw:rounded-lg tw:shadow tw:py-4 tw:px-6 tw:flex tw:flex-row tw:items-center tw:gap-4 tw:justify-between">
|
||||
<span className="tw:text-base-100 tw:text-left">
|
||||
Hi <b>{impersonating.admin}</b>, you are currently impersonating <b>{impersonating.user}</b>
|
||||
</span>
|
||||
<button className="tw-daisy-btn tw-daisy-btn-neutral" onClick={stopImpersonating}>
|
||||
<button className="tw:daisy-btn tw:daisy-btn-neutral" onClick={stopImpersonating}>
|
||||
Stop Impersonating
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -151,13 +151,13 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const btnClasses = `tw-daisy-btn tw-capitalize tw-w-full tw-mt-4 ${
|
||||
signInFailed ? 'tw-daisy-btn-warning' : 'tw-daisy-btn-primary'
|
||||
} tw-transition-colors tw-ease-in-out tw-duration-300 ${horFlexClassesNoSm}`
|
||||
const btnClasses = `tw:daisy-btn tw:capitalize tw:w-full tw:mt-4 ${
|
||||
signInFailed ? 'tw:daisy-btn-warning' : 'tw:daisy-btn-primary'
|
||||
} tw:transition-colors tw:ease-in-out tw:duration-300 ${horFlexClassesNoSm}`
|
||||
const noBueno = (
|
||||
<>
|
||||
<WarningIcon />
|
||||
<span className="tw-pl-2">{signInFailed}</span>
|
||||
<span className="tw:pl-2">{signInFailed}</span>
|
||||
<WarningIcon />
|
||||
</>
|
||||
)
|
||||
|
@ -166,22 +166,22 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
return (
|
||||
<WrapForm>
|
||||
<H1>Email Sent</H1>
|
||||
<p className="tw-text-inherit tw-text-lg tw-text-center">
|
||||
<p className="tw:text-inherit tw:text-lg tw:text-center">
|
||||
Go check your inbox for an email from <b>FreeSewing.org</b>
|
||||
</p>
|
||||
<p className="tw-text-inherit tw-text-lg tw-text-center">
|
||||
<p className="tw:text-inherit tw:text-lg tw:text-center">
|
||||
Click the sign-in link in that email to sign in to your FreeSewing account.
|
||||
</p>
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-items-center tw-justify-center tw-p-8">
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:items-center tw:justify-center tw:p-8">
|
||||
<button
|
||||
className="tw-daisy-btn tw-daisy-btn-outline tw-daisy-btn-sm"
|
||||
className="tw:daisy-btn tw:daisy-btn-outline tw:daisy-btn-sm"
|
||||
onClick={() => setMagicLinkSent(false)}
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<Link
|
||||
href="/support"
|
||||
className="tw-daisy-btn tw-daisy-btn-outline tw-daisy-btn-sm hover:tw-no-underline"
|
||||
className="tw:daisy-btn tw:daisy-btn-outline tw:daisy-btn-sm tw:hover:no-underline"
|
||||
>
|
||||
Contact support
|
||||
</Link>
|
||||
|
@ -195,11 +195,11 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
{...{ mfaCode, setMfaCode }}
|
||||
onSubmit={signinHandler}
|
||||
post={
|
||||
<div className="tw-flex tw-flex-row tw-gap-4 tw-items-center tw-justify-center tw-p-8">
|
||||
<button className="tw-daisy-btn tw-daisy-btn-ghost" onClick={() => setMfa(false)}>
|
||||
<div className="tw:flex tw:flex-row tw:gap-4 tw:items-center tw:justify-center tw:p-8">
|
||||
<button className="tw:daisy-btn tw:daisy-btn-ghost" onClick={() => setMfa(false)}>
|
||||
Back
|
||||
</button>
|
||||
<Link href="/support" className="tw-daisy-btn tw-daisy-btn-ghost">
|
||||
<Link href="/support" className="tw:daisy-btn tw:daisy-btn-ghost">
|
||||
Contact support
|
||||
</Link>
|
||||
</div>
|
||||
|
@ -222,7 +222,7 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
)}
|
||||
{magicLink ? (
|
||||
<button
|
||||
className={`${btnClasses} tw-daisy-btn-lg`}
|
||||
className={`${btnClasses} tw:daisy-btn-lg`}
|
||||
tabIndex="-1"
|
||||
role="button"
|
||||
onClick={signinHandler}
|
||||
|
@ -231,11 +231,11 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
noBueno
|
||||
) : (
|
||||
<>
|
||||
<span className="tw-hidden lg:tw-block">
|
||||
<span className="tw:hidden tw:lg:block">
|
||||
<EmailIcon />
|
||||
</span>
|
||||
<span className="tw-pl-2">Email me a sign-in link</span>
|
||||
<span className="tw-hidden lg:tw-block">
|
||||
<span className="tw:pl-2">Email me a sign-in link</span>
|
||||
<span className="tw:hidden tw:lg:block">
|
||||
<EmailIcon />
|
||||
</span>
|
||||
</>
|
||||
|
@ -255,11 +255,11 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
noBueno
|
||||
) : (
|
||||
<>
|
||||
<span className="tw-hidden lg:tw-block">
|
||||
<span className="tw:hidden tw:lg:block">
|
||||
<KeyIcon />
|
||||
</span>
|
||||
<span className="tw-pl-2">Sign in</span>
|
||||
<span className="tw-hidden lg:tw-block">
|
||||
<span className="tw:pl-2">Sign in</span>
|
||||
<span className="tw:hidden tw:lg:block">
|
||||
<LockIcon />
|
||||
</span>
|
||||
</>
|
||||
|
@ -268,19 +268,19 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
</>
|
||||
)}
|
||||
<button
|
||||
className={`tw-block md:tw-flex md:tw-flex-row md:tw-justify-between md:tw-items-center tw-daisy-btn tw-daisy-btn-primary tw-daisy-btn-outline tw-w-full tw-mt-8`}
|
||||
className={`tw:block tw:md:flex tw:md:flex-row tw:md:justify-between tw:md:items-center tw:daisy-btn tw:daisy-btn-primary tw:daisy-btn-outline tw:w-full tw:mt-8`}
|
||||
onClick={() => setMagicLink(!magicLink)}
|
||||
>
|
||||
<span className="tw-hidden lg:tw-block">{magicLink ? <LockIcon /> : <EmailIcon />}</span>
|
||||
<span className="tw:hidden tw:lg:block">{magicLink ? <LockIcon /> : <EmailIcon />}</span>
|
||||
{magicLink ? 'Use your password' : 'Email me a sign-in link'}
|
||||
<span className="tw-hidden lg:tw-block">{magicLink ? <KeyIcon /> : <EmailIcon />}</span>
|
||||
<span className="tw:hidden tw:lg:block">{magicLink ? <KeyIcon /> : <EmailIcon />}</span>
|
||||
</button>
|
||||
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-items-center tw-mt-2">
|
||||
<div className="tw:grid tw:grid-cols-1 tw:md:grid-cols-2 tw:gap-2 tw:items-center tw:mt-2">
|
||||
{['Google', 'Github'].map((provider) => (
|
||||
<button
|
||||
key={provider}
|
||||
id={provider}
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-secondary`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-secondary`}
|
||||
onClick={() => initOauth(provider)}
|
||||
>
|
||||
{provider === 'Google' ? <GoogleIcon stroke={0} /> : <GitHubIcon />}
|
||||
|
@ -290,7 +290,7 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
</div>
|
||||
{seenBefore ? (
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-neutral tw-daisy-btn-outline tw-mt-2 tw-w-full`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-neutral tw:daisy-btn-outline tw:mt-2 tw:w-full`}
|
||||
onClick={() => setSeenUser(false)}
|
||||
>
|
||||
<UserIcon />
|
||||
|
@ -298,10 +298,10 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
</button>
|
||||
) : (
|
||||
<Link
|
||||
className={`${horFlexClasses} tw-daisy-btn tw-daisy-btn-lg tw-daisy-btn-neutral tw-mt-2 hover:tw-text-neutral-content hover:tw-no-underline`}
|
||||
className={`${horFlexClasses} tw:daisy-btn tw:daisy-btn-lg tw:daisy-btn-neutral tw:mt-2 tw:hover:text-neutral-content tw:hover:no-underline`}
|
||||
href="/signup"
|
||||
>
|
||||
<FreeSewingIcon className="tw-h-10 tw-w-10" />
|
||||
<FreeSewingIcon className="tw:h-10 tw:w-10" />
|
||||
Sign up here
|
||||
</Link>
|
||||
)}
|
||||
|
@ -309,12 +309,12 @@ export const SignIn = ({ onSuccess = false, silent = false }) => {
|
|||
)
|
||||
}
|
||||
|
||||
const WrapForm = ({ children }) => <div className="tw-text-center tw-py-12">{children}</div>
|
||||
const WrapForm = ({ children }) => <div className="tw:text-center tw:py-12">{children}</div>
|
||||
|
||||
const MfaForm = ({ mfaCode, setMfaCode, onSubmit, post = [] }) => (
|
||||
<WrapForm>
|
||||
<H1>MFA Code</H1>
|
||||
<p className="tw-text-inherit tw-text-lg tw-text-center">
|
||||
<p className="tw:text-inherit tw:text-lg tw:text-center">
|
||||
Please provide a one-time MFA code, or a backup scratch code
|
||||
</p>
|
||||
<MfaInput
|
||||
|
@ -323,16 +323,16 @@ const MfaForm = ({ mfaCode, setMfaCode, onSubmit, post = [] }) => (
|
|||
value={mfaCode}
|
||||
/>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-capitalize tw-w-full tw-mt-4 tw-daisy-btn-primary ${horFlexClassesNoSm}`}
|
||||
className={`tw:daisy-btn tw:capitalize tw:w-full tw:mt-4 tw:daisy-btn-primary ${horFlexClassesNoSm}`}
|
||||
tabIndex="-1"
|
||||
role="button"
|
||||
onClick={onSubmit}
|
||||
>
|
||||
<span className="tw-hidden lg:tw-block">
|
||||
<span className="tw:hidden tw:lg:block">
|
||||
<KeyIcon />
|
||||
</span>
|
||||
<span className="tw-pl-2">Sign In</span>
|
||||
<span className="tw-hidden lg:tw-block">
|
||||
<span className="tw:pl-2">Sign In</span>
|
||||
<span className="tw:hidden tw:lg:block">
|
||||
<LockIcon />
|
||||
</span>
|
||||
</button>
|
||||
|
@ -428,7 +428,7 @@ export const SignInConfirmation = ({ onSuccess = false }) => {
|
|||
return (
|
||||
<>
|
||||
<h1>One moment please</h1>
|
||||
<Spinner className="tw-w-8 tw-h-8 tw-m-auto tw-animate-spin" />
|
||||
<Spinner className="tw:w-8 tw:h-8 tw:m-auto tw:animate-spin" />
|
||||
</>
|
||||
)
|
||||
|
||||
|
@ -438,7 +438,7 @@ export const SignInConfirmation = ({ onSuccess = false }) => {
|
|||
/*
|
||||
* This is the generic component that will handle the Oauth callback
|
||||
*/
|
||||
function OauthCallback({ provider = false }) {
|
||||
export const OauthCallback = ({ provider = false }) => {
|
||||
const [error, setError] = useState(false)
|
||||
const backend = useBackend()
|
||||
const { setAccount, setToken, setSeenUser } = useAccount()
|
||||
|
@ -474,7 +474,7 @@ function OauthCallback({ provider = false }) {
|
|||
) : (
|
||||
<>
|
||||
<h2>One moment please</h2>
|
||||
<Spinner className="tw-w-8 tw-h-8 tw-m-auto tw-animate-spin" />
|
||||
<Spinner className="tw:w-8 tw:h-8 tw:m-auto tw:animate-spin" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue