@fab1o978/react-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -0
- package/dist/components/Badge/index.cjs +47 -0
- package/dist/components/Badge/index.cjs.map +1 -0
- package/dist/components/Badge/index.css +112 -0
- package/dist/components/Badge/index.css.map +1 -0
- package/dist/components/Badge/index.d.cts +14 -0
- package/dist/components/Badge/index.d.ts +14 -0
- package/dist/components/Badge/index.js +45 -0
- package/dist/components/Badge/index.js.map +1 -0
- package/dist/components/Button/index.cjs +64 -0
- package/dist/components/Button/index.cjs.map +1 -0
- package/dist/components/Button/index.css +159 -0
- package/dist/components/Button/index.css.map +1 -0
- package/dist/components/Button/index.d.cts +13 -0
- package/dist/components/Button/index.d.ts +13 -0
- package/dist/components/Button/index.js +58 -0
- package/dist/components/Button/index.js.map +1 -0
- package/dist/components/ColorPicker/index.cjs +523 -0
- package/dist/components/ColorPicker/index.cjs.map +1 -0
- package/dist/components/ColorPicker/index.css +308 -0
- package/dist/components/ColorPicker/index.css.map +1 -0
- package/dist/components/ColorPicker/index.d.cts +35 -0
- package/dist/components/ColorPicker/index.d.ts +35 -0
- package/dist/components/ColorPicker/index.js +521 -0
- package/dist/components/ColorPicker/index.js.map +1 -0
- package/dist/components/Input/index.cjs +86 -0
- package/dist/components/Input/index.cjs.map +1 -0
- package/dist/components/Input/index.css +170 -0
- package/dist/components/Input/index.css.map +1 -0
- package/dist/components/Input/index.d.cts +15 -0
- package/dist/components/Input/index.d.ts +15 -0
- package/dist/components/Input/index.js +80 -0
- package/dist/components/Input/index.js.map +1 -0
- package/dist/components/RainCanvas/index.cjs +227 -0
- package/dist/components/RainCanvas/index.cjs.map +1 -0
- package/dist/components/RainCanvas/index.css +32 -0
- package/dist/components/RainCanvas/index.css.map +1 -0
- package/dist/components/RainCanvas/index.d.cts +12 -0
- package/dist/components/RainCanvas/index.d.ts +12 -0
- package/dist/components/RainCanvas/index.js +225 -0
- package/dist/components/RainCanvas/index.js.map +1 -0
- package/dist/components/Timeline/index.cjs +169 -0
- package/dist/components/Timeline/index.cjs.map +1 -0
- package/dist/components/Timeline/index.css +247 -0
- package/dist/components/Timeline/index.css.map +1 -0
- package/dist/components/Timeline/index.d.cts +22 -0
- package/dist/components/Timeline/index.d.ts +22 -0
- package/dist/components/Timeline/index.js +167 -0
- package/dist/components/Timeline/index.js.map +1 -0
- package/dist/index.cjs +993 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1019 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +982 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Input/Input.module.scss","../../../src/components/Input/Input.tsx"],"names":["wrapper","fullWidth","label","inputWrapper","input","error","sm","md","lg","adornment","adornmentEnd","withStart","withEnd","helperText","errorText"],"mappings":"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","file":"index.js","sourcesContent":["@import url(\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap\");\n:root {\n --accent: #3b82f6;\n --accent-dot: rgb(82.52, 145, 247.08);\n --accent-track: #3b82f6;\n --accent-ring: #3b82f6;\n --accent-glow: rgba(59, 130, 246, 0.3);\n --accent-light: rgb(157.485, 188.725, 239.765);\n --color-primary-50: rgb(169.3455, 194.6925, 236.1045);\n --color-primary-100: rgb(149.4545, 184.4575, 241.6455);\n --color-primary-400: rgb(82.52, 145, 247.08);\n --color-primary-500: #3b82f6;\n --color-primary-600: rgb(29.8390243902, 111.4024390244, 244.6609756098);\n --color-primary-700: rgb(10.712195122, 95.2195121951, 233.287804878);\n --color-neutral-0: #ffffff;\n --color-neutral-100: #f3f4f6;\n --color-neutral-200: #e5e7eb;\n --color-neutral-400: #9ca3af;\n --color-neutral-600: #4b5563;\n --color-neutral-900: #111827;\n --color-success-500: #22c55e;\n --color-success-600: #16a34a;\n --color-danger-500: #ef4444;\n --color-danger-600: #dc2626;\n --color-warning-500: #f59e0b;\n --color-warning-600: #d97706;\n --font-family-base: \"Inter\", system-ui, -apple-system, sans-serif;\n --font-size-xs: 0.75rem;\n --font-size-sm: 0.875rem;\n --font-size-md: 1rem;\n --font-size-lg: 1.125rem;\n --spacing-1: 0.25rem;\n --spacing-2: 0.5rem;\n --spacing-3: 0.75rem;\n --spacing-4: 1rem;\n --radius-sm: 0.25rem;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --radius-full: 9999px;\n --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --transition-fast: 150ms ease;\n --color-surface: #ffffff;\n --color-surface-elevated: #ffffff;\n}\n\n[data-theme=dark] {\n --color-neutral-0: #0f172a;\n --color-neutral-100: #1e293b;\n --color-neutral-200: #334155;\n --color-neutral-400: #94a3b8;\n --color-neutral-600: #cbd5e1;\n --color-neutral-900: #f8fafc;\n --color-surface: #1e293b;\n --color-surface-elevated: #273549;\n --color-primary-50: #172554;\n --color-primary-100: #1e3a8a;\n --accent-light: #172554;\n --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.4);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.5), 0 2px 4px -2px rgb(0 0 0 / 0.4);\n}\n\n.wrapper {\n display: inline-flex;\n flex-direction: column;\n gap: var(--spacing-1);\n}\n\n.fullWidth {\n width: 100%;\n}\n\n.label {\n font-family: var(--font-family-base);\n font-size: var(--font-size-sm);\n font-weight: 500;\n color: var(--color-neutral-900);\n letter-spacing: -0.01em;\n}\n\n.inputWrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.input {\n width: 100%;\n font-family: var(--font-family-base);\n border: 1px solid var(--color-neutral-200);\n border-radius: var(--radius-md);\n background-color: var(--color-neutral-0);\n color: var(--color-neutral-900);\n outline: none;\n transition: border-color var(--transition-fast), box-shadow var(--transition-fast);\n}\n\n.input::placeholder {\n color: var(--color-neutral-400);\n}\n\n.input:focus {\n border-color: var(--color-primary-500);\n box-shadow: 0 0 0 3px var(--color-primary-100);\n}\n\n.input:disabled {\n background-color: var(--color-neutral-100);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.input.error {\n border-color: var(--color-danger-500);\n}\n\n.input.error:focus {\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);\n}\n\n/* Sizes */\n.sm .input {\n font-size: var(--font-size-xs);\n padding: var(--spacing-1) var(--spacing-2);\n height: 2rem;\n}\n\n.md .input {\n font-size: var(--font-size-sm);\n padding: var(--spacing-2) var(--spacing-3);\n height: 2.5rem;\n}\n\n.lg .input {\n font-size: var(--font-size-md);\n padding: var(--spacing-3) var(--spacing-4);\n height: 3rem;\n}\n\n/* Adornments */\n.adornment {\n position: absolute;\n left: var(--spacing-3);\n display: flex;\n align-items: center;\n color: var(--color-neutral-400);\n pointer-events: none;\n}\n\n.adornmentEnd {\n left: unset;\n right: var(--spacing-3);\n}\n\n.sm .withStart {\n padding-left: 2rem;\n}\n\n.md .withStart {\n padding-left: 2.25rem;\n}\n\n.lg .withStart {\n padding-left: 2.5rem;\n}\n\n.sm .withEnd {\n padding-right: 2rem;\n}\n\n.md .withEnd {\n padding-right: 2.25rem;\n}\n\n.lg .withEnd {\n padding-right: 2.5rem;\n}\n\n.helperText {\n font-family: var(--font-family-base);\n font-size: var(--font-size-xs);\n color: var(--color-neutral-400);\n}\n\n.errorText {\n font-family: var(--font-family-base);\n font-size: var(--font-size-xs);\n color: var(--color-danger-500);\n}\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3N0eWxlcy90b2tlbnMuc2NzcyIsIklucHV0Lm1vZHVsZS5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVRO0FBS1I7RUFFRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBR0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUdBO0VBQ0E7RUFHQTtFQUdBO0VBQ0E7OztBQVFGO0VBRUU7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBR0E7RUFDQTtFQUdBO0VBQ0E7RUFJQTtFQUdBO0VBQ0E7OztBQ2pHRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFOzs7QUFHRjtBQUNBO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0FBQ0E7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTs7O0FBR0Y7RUFBaUI7OztBQUNqQjtFQUFpQjs7O0FBQ2pCO0VBQWlCOzs7QUFFakI7RUFBZTs7O0FBQ2Y7RUFBZTs7O0FBQ2Y7RUFBZTs7O0FBRWY7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBIiwic291cmNlc0NvbnRlbnQiOlsiQHVzZSBcInNhc3M6Y29sb3JcIjtcblxuQGltcG9ydCB1cmwoXCJodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2NzczI/ZmFtaWx5PUludGVyOndnaHRANDAwOzUwMDs2MDAmZGlzcGxheT1zd2FwXCIpO1xuXG4vLyBBY2NlbnQgZGkgZGVmYXVsdCDigJQgY2FtYmlhIHF1aSBwZXIgYWdnaW9ybmFyZSB0dXR0YSBsYSBsaWJyZXJpYVxuJGFjY2VudDogIzNiODJmNjtcblxuOnJvb3Qge1xuICAvLyBBY2NlbnQgc2NhbGUg4oCUIGRlcml2YXRhIGRhICRhY2NlbnQgYSBjb21waWxlIHRpbWVcbiAgLS1hY2NlbnQ6ICAgICAgICAjeyRhY2NlbnR9O1xuICAtLWFjY2VudC1kb3Q6ICAgICN7Y29sb3Iuc2NhbGUoJGFjY2VudCwgJGxpZ2h0bmVzczogMTIlKX07XG4gIC0tYWNjZW50LXRyYWNrOiAgI3skYWNjZW50fTtcbiAgLS1hY2NlbnQtcmluZzogICAjeyRhY2NlbnR9O1xuICAtLWFjY2VudC1nbG93OiAgICN7Y29sb3IuY2hhbmdlKCRhY2NlbnQsICRhbHBoYTogMC4zKX07XG4gIC0tYWNjZW50LWxpZ2h0OiAgI3tjb2xvci5zY2FsZSgkYWNjZW50LCAkbGlnaHRuZXNzOiA0NSUsICRzYXR1cmF0aW9uOiAtMjAlKX07XG5cbiAgLy8gUHJpbWFyeSBzY2FsZSAobWFudGVudXRhIHBlciByZXRyb2NvbXBhdGliaWxpdMOgIGNvbiBCdXR0b24sIEJhZGdlLCBJbnB1dClcbiAgLS1jb2xvci1wcmltYXJ5LTUwOiAgI3tjb2xvci5zY2FsZSgkYWNjZW50LCAkbGlnaHRuZXNzOiA0OSUsICRzYXR1cmF0aW9uOiAtMzAlKX07XG4gIC0tY29sb3ItcHJpbWFyeS0xMDA6ICN7Y29sb3Iuc2NhbGUoJGFjY2VudCwgJGxpZ2h0bmVzczogNDIlLCAkc2F0dXJhdGlvbjogLTE1JSl9O1xuICAtLWNvbG9yLXByaW1hcnktNDAwOiAje2NvbG9yLnNjYWxlKCRhY2NlbnQsICRsaWdodG5lc3M6IDEyJSl9O1xuICAtLWNvbG9yLXByaW1hcnktNTAwOiAjeyRhY2NlbnR9O1xuICAtLWNvbG9yLXByaW1hcnktNjAwOiAje2NvbG9yLnNjYWxlKCRhY2NlbnQsICRsaWdodG5lc3M6IC0xMCUpfTtcbiAgLS1jb2xvci1wcmltYXJ5LTcwMDogI3tjb2xvci5zY2FsZSgkYWNjZW50LCAkbGlnaHRuZXNzOiAtMjAlKX07XG5cbiAgLy8gTmV1dHJhbFxuICAtLWNvbG9yLW5ldXRyYWwtMDogICAjZmZmZmZmO1xuICAtLWNvbG9yLW5ldXRyYWwtMTAwOiAjZjNmNGY2O1xuICAtLWNvbG9yLW5ldXRyYWwtMjAwOiAjZTVlN2ViO1xuICAtLWNvbG9yLW5ldXRyYWwtNDAwOiAjOWNhM2FmO1xuICAtLWNvbG9yLW5ldXRyYWwtNjAwOiAjNGI1NTYzO1xuICAtLWNvbG9yLW5ldXRyYWwtOTAwOiAjMTExODI3O1xuXG4gIC8vIFNlbWFudGljXG4gIC0tY29sb3Itc3VjY2Vzcy01MDA6ICMyMmM1NWU7XG4gIC0tY29sb3Itc3VjY2Vzcy02MDA6ICMxNmEzNGE7XG4gIC0tY29sb3ItZGFuZ2VyLTUwMDogICNlZjQ0NDQ7XG4gIC0tY29sb3ItZGFuZ2VyLTYwMDogICNkYzI2MjY7XG4gIC0tY29sb3Itd2FybmluZy01MDA6ICNmNTllMGI7XG4gIC0tY29sb3Itd2FybmluZy02MDA6ICNkOTc3MDY7XG5cbiAgLy8gVHlwb2dyYXBoeVxuICAtLWZvbnQtZmFtaWx5LWJhc2U6IFwiSW50ZXJcIiwgc3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBzYW5zLXNlcmlmO1xuICAtLWZvbnQtc2l6ZS14czogMC43NXJlbTtcbiAgLS1mb250LXNpemUtc206IDAuODc1cmVtO1xuICAtLWZvbnQtc2l6ZS1tZDogMXJlbTtcbiAgLS1mb250LXNpemUtbGc6IDEuMTI1cmVtO1xuXG4gIC8vIFNwYWNpbmdcbiAgLS1zcGFjaW5nLTE6IDAuMjVyZW07XG4gIC0tc3BhY2luZy0yOiAwLjVyZW07XG4gIC0tc3BhY2luZy0zOiAwLjc1cmVtO1xuICAtLXNwYWNpbmctNDogMXJlbTtcblxuICAvLyBSYWRpdXNcbiAgLS1yYWRpdXMtc206ICAgMC4yNXJlbTtcbiAgLS1yYWRpdXMtbWQ6ICAgMC4zNzVyZW07XG4gIC0tcmFkaXVzLWxnOiAgIDAuNXJlbTtcbiAgLS1yYWRpdXMtZnVsbDogOTk5OXB4O1xuXG4gIC8vIFNoYWRvd3NcbiAgLS1zaGFkb3ctc206IDAgMXB4IDJweCAwIHJnYigwIDAgMCAvIDAuMDUpO1xuICAtLXNoYWRvdy1tZDogMCA0cHggNnB4IC0xcHggcmdiKDAgMCAwIC8gMC4xKSwgMCAycHggNHB4IC0ycHggcmdiKDAgMCAwIC8gMC4xKTtcblxuICAvLyBUcmFuc2l0aW9uc1xuICAtLXRyYW5zaXRpb24tZmFzdDogMTUwbXMgZWFzZTtcblxuICAvLyBTdXJmYWNlIChiYWNrZ3JvdW5kIGRpIGNhcmQvcGFuZWwpXG4gIC0tY29sb3Itc3VyZmFjZTogICAgICAgICAgI2ZmZmZmZjtcbiAgLS1jb2xvci1zdXJmYWNlLWVsZXZhdGVkOiAjZmZmZmZmO1xufVxuXG4vLyDilIDilIDilIAgRGFyayB0aGVtZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIEFwcGxpY2F0byB2aWEgZGF0YS10aGVtZT1cImRhcmtcIiBzdWxsJ2VsZW1lbnRvIHJvb3QgKGdlc3RpdG8gZGEgU3Rvcnlib29rIGRlY29yYXRvclxuLy8gZSBkYWxsJ2FwcCBjb25zdW1lcikuIEkgY29tcG9uZW50aSBub24gZGV2b25vIGZhcmUgbnVsbGEgZGkgc3BlY2lhbGU6IGJhc3RhIGNoZVxuLy8gdXNpbm8gaSB0b2tlbiB2YXIoKSBlIHJpY2V2ZXJhbm5vIGF1dG9tYXRpY2FtZW50ZSBpIHZhbG9yaSBkYXJrLlxuXG5bZGF0YS10aGVtZT1cImRhcmtcIl0ge1xuICAvLyBOZXV0cmFsIChzY2FsYSBpbnZlcnRpdGEpXG4gIC0tY29sb3ItbmV1dHJhbC0wOiAgICMwZjE3MmE7XG4gIC0tY29sb3ItbmV1dHJhbC0xMDA6ICMxZTI5M2I7XG4gIC0tY29sb3ItbmV1dHJhbC0yMDA6ICMzMzQxNTU7XG4gIC0tY29sb3ItbmV1dHJhbC00MDA6ICM5NGEzYjg7XG4gIC0tY29sb3ItbmV1dHJhbC02MDA6ICNjYmQ1ZTE7XG4gIC0tY29sb3ItbmV1dHJhbC05MDA6ICNmOGZhZmM7XG5cbiAgLy8gU3VyZmFjZVxuICAtLWNvbG9yLXN1cmZhY2U6ICAgICAgICAgICMxZTI5M2I7XG4gIC0tY29sb3Itc3VyZmFjZS1lbGV2YXRlZDogIzI3MzU0OTtcblxuICAvLyBQcmltYXJ5IHNjYWxlIGRhcmsgKHBlciBpbCBkZWZhdWx0IGFjY2VudCBibHUg4oCUIGxlIHNmdW1hdHVyZSBjaGlhcmUgZGl2ZW50YW5vIHNjdXJlKVxuICAtLWNvbG9yLXByaW1hcnktNTA6ICAjMTcyNTU0O1xuICAtLWNvbG9yLXByaW1hcnktMTAwOiAjMWUzYThhO1xuICAvLyA0MDAgLyA1MDAgLyA2MDAgLyA3MDAgcmltYW5nb25vIGludmFyaWF0aSAoYWJiYXN0YW56YSBzYXR1cmkgc3UgYmcgc2N1cm8pXG5cbiAgLy8gQWNjZW50IGxpZ2h0OiB2YXJpYW50ZSBzY3VyYVxuICAtLWFjY2VudC1saWdodDogIzE3MjU1NDtcblxuICAvLyBTaGFkb3dzIChwacO5IGZvcnRpIHN1IGJnIHNjdXJvKVxuICAtLXNoYWRvdy1zbTogMCAxcHggMnB4IDAgcmdiKDAgMCAwIC8gMC40KTtcbiAgLS1zaGFkb3ctbWQ6IDAgNHB4IDZweCAtMXB4IHJnYigwIDAgMCAvIDAuNSksIDAgMnB4IDRweCAtMnB4IHJnYigwIDAgMCAvIDAuNCk7XG59XG4iLCJAaW1wb3J0IFwiLi4vLi4vc3R5bGVzL3Rva2Vucy5zY3NzXCI7XG5cbi53cmFwcGVyIHtcbiAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGdhcDogdmFyKC0tc3BhY2luZy0xKTtcbn1cblxuLmZ1bGxXaWR0aCB7XG4gIHdpZHRoOiAxMDAlO1xufVxuXG4ubGFiZWwge1xuICBmb250LWZhbWlseTogdmFyKC0tZm9udC1mYW1pbHktYmFzZSk7XG4gIGZvbnQtc2l6ZTogdmFyKC0tZm9udC1zaXplLXNtKTtcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgY29sb3I6IHZhcigtLWNvbG9yLW5ldXRyYWwtOTAwKTtcbiAgbGV0dGVyLXNwYWNpbmc6IC0wLjAxZW07XG59XG5cbi5pbnB1dFdyYXBwZXIge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG59XG5cbi5pbnB1dCB7XG4gIHdpZHRoOiAxMDAlO1xuICBmb250LWZhbWlseTogdmFyKC0tZm9udC1mYW1pbHktYmFzZSk7XG4gIGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWNvbG9yLW5ldXRyYWwtMjAwKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tcmFkaXVzLW1kKTtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tY29sb3ItbmV1dHJhbC0wKTtcbiAgY29sb3I6IHZhcigtLWNvbG9yLW5ldXRyYWwtOTAwKTtcbiAgb3V0bGluZTogbm9uZTtcbiAgdHJhbnNpdGlvbjogYm9yZGVyLWNvbG9yIHZhcigtLXRyYW5zaXRpb24tZmFzdCksIGJveC1zaGFkb3cgdmFyKC0tdHJhbnNpdGlvbi1mYXN0KTtcbn1cblxuLmlucHV0OjpwbGFjZWhvbGRlciB7XG4gIGNvbG9yOiB2YXIoLS1jb2xvci1uZXV0cmFsLTQwMCk7XG59XG5cbi5pbnB1dDpmb2N1cyB7XG4gIGJvcmRlci1jb2xvcjogdmFyKC0tY29sb3ItcHJpbWFyeS01MDApO1xuICBib3gtc2hhZG93OiAwIDAgMCAzcHggdmFyKC0tY29sb3ItcHJpbWFyeS0xMDApO1xufVxuXG4uaW5wdXQ6ZGlzYWJsZWQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1jb2xvci1uZXV0cmFsLTEwMCk7XG4gIGN1cnNvcjogbm90LWFsbG93ZWQ7XG4gIG9wYWNpdHk6IDAuNjtcbn1cblxuLmlucHV0LmVycm9yIHtcbiAgYm9yZGVyLWNvbG9yOiB2YXIoLS1jb2xvci1kYW5nZXItNTAwKTtcbn1cblxuLmlucHV0LmVycm9yOmZvY3VzIHtcbiAgYm94LXNoYWRvdzogMCAwIDAgM3B4IHJnYigyMzkgNjggNjggLyAwLjE1KTtcbn1cblxuLyogU2l6ZXMgKi9cbi5zbSAuaW5wdXQge1xuICBmb250LXNpemU6IHZhcigtLWZvbnQtc2l6ZS14cyk7XG4gIHBhZGRpbmc6IHZhcigtLXNwYWNpbmctMSkgdmFyKC0tc3BhY2luZy0yKTtcbiAgaGVpZ2h0OiAycmVtO1xufVxuXG4ubWQgLmlucHV0IHtcbiAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtc20pO1xuICBwYWRkaW5nOiB2YXIoLS1zcGFjaW5nLTIpIHZhcigtLXNwYWNpbmctMyk7XG4gIGhlaWdodDogMi41cmVtO1xufVxuXG4ubGcgLmlucHV0IHtcbiAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtbWQpO1xuICBwYWRkaW5nOiB2YXIoLS1zcGFjaW5nLTMpIHZhcigtLXNwYWNpbmctNCk7XG4gIGhlaWdodDogM3JlbTtcbn1cblxuLyogQWRvcm5tZW50cyAqL1xuLmFkb3JubWVudCB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgbGVmdDogdmFyKC0tc3BhY2luZy0zKTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgY29sb3I6IHZhcigtLWNvbG9yLW5ldXRyYWwtNDAwKTtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbi5hZG9ybm1lbnRFbmQge1xuICBsZWZ0OiB1bnNldDtcbiAgcmlnaHQ6IHZhcigtLXNwYWNpbmctMyk7XG59XG5cbi5zbSAud2l0aFN0YXJ0IHsgcGFkZGluZy1sZWZ0OiAycmVtOyB9XG4ubWQgLndpdGhTdGFydCB7IHBhZGRpbmctbGVmdDogMi4yNXJlbTsgfVxuLmxnIC53aXRoU3RhcnQgeyBwYWRkaW5nLWxlZnQ6IDIuNXJlbTsgfVxuXG4uc20gLndpdGhFbmQgeyBwYWRkaW5nLXJpZ2h0OiAycmVtOyB9XG4ubWQgLndpdGhFbmQgeyBwYWRkaW5nLXJpZ2h0OiAyLjI1cmVtOyB9XG4ubGcgLndpdGhFbmQgeyBwYWRkaW5nLXJpZ2h0OiAyLjVyZW07IH1cblxuLmhlbHBlclRleHQge1xuICBmb250LWZhbWlseTogdmFyKC0tZm9udC1mYW1pbHktYmFzZSk7XG4gIGZvbnQtc2l6ZTogdmFyKC0tZm9udC1zaXplLXhzKTtcbiAgY29sb3I6IHZhcigtLWNvbG9yLW5ldXRyYWwtNDAwKTtcbn1cblxuLmVycm9yVGV4dCB7XG4gIGZvbnQtZmFtaWx5OiB2YXIoLS1mb250LWZhbWlseS1iYXNlKTtcbiAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUteHMpO1xuICBjb2xvcjogdmFyKC0tY29sb3ItZGFuZ2VyLTUwMCk7XG59XG4iXX0= */","import React from \"react\";\nimport styles from \"./Input.module.scss\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n label?: string;\n helperText?: string;\n errorText?: string;\n size?: InputSize;\n fullWidth?: boolean;\n startAdornment?: React.ReactNode;\n endAdornment?: React.ReactNode;\n}\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n label,\n helperText,\n errorText,\n size = \"md\",\n fullWidth = false,\n startAdornment,\n endAdornment,\n id,\n className,\n ...props\n },\n ref\n ) => {\n const inputId = id ?? (label ? label.toLowerCase().replace(/\\s+/g, \"-\") : undefined);\n const hasError = Boolean(errorText);\n\n return (\n <div\n className={[\n styles.wrapper,\n fullWidth ? styles.fullWidth : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n </label>\n )}\n <div className={[styles.inputWrapper, styles[size]].join(\" \")}>\n {startAdornment && (\n <span className={styles.adornment}>{startAdornment}</span>\n )}\n <input\n ref={ref}\n id={inputId}\n className={[\n styles.input,\n hasError ? styles.error : \"\",\n startAdornment ? styles.withStart : \"\",\n endAdornment ? styles.withEnd : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n aria-invalid={hasError}\n aria-describedby={\n errorText\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined\n }\n {...props}\n />\n {endAdornment && (\n <span className={[styles.adornment, styles.adornmentEnd].join(\" \")}>\n {endAdornment}\n </span>\n )}\n </div>\n {errorText && (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {errorText}\n </span>\n )}\n {helperText && !errorText && (\n <span id={`${inputId}-helper`} className={styles.helperText}>\n {helperText}\n </span>\n )}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n"]}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
|
|
6
|
+
// src/components/RainCanvas/RainCanvas.tsx
|
|
7
|
+
|
|
8
|
+
// src/components/RainCanvas/RainCanvas.module.scss
|
|
9
|
+
var RainCanvas_module_default = {
|
|
10
|
+
wrapper: "RainCanvas_module_wrapper2",
|
|
11
|
+
trailCanvas: "RainCanvas_module_trailCanvas2",
|
|
12
|
+
content: "RainCanvas_module_content2",
|
|
13
|
+
dropContainer: "RainCanvas_module_dropContainer2"
|
|
14
|
+
};
|
|
15
|
+
var _nextId = 0;
|
|
16
|
+
function randomBetween(a, b) {
|
|
17
|
+
return a + Math.random() * (b - a);
|
|
18
|
+
}
|
|
19
|
+
function createStaticDrop(width, height) {
|
|
20
|
+
return {
|
|
21
|
+
id: _nextId++,
|
|
22
|
+
kind: "static",
|
|
23
|
+
x: randomBetween(10, width - 10),
|
|
24
|
+
y: randomBetween(10, height - 10),
|
|
25
|
+
radius: randomBetween(4, 11),
|
|
26
|
+
age: 0,
|
|
27
|
+
maxAge: randomBetween(120, 400),
|
|
28
|
+
speed: 0,
|
|
29
|
+
trail: []
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
var RainCanvas = ({
|
|
33
|
+
dropCount = 55,
|
|
34
|
+
background = "linear-gradient(160deg, #0f172a 0%, #1e3a5f 60%, #0f2a4a 100%)",
|
|
35
|
+
children,
|
|
36
|
+
className,
|
|
37
|
+
style
|
|
38
|
+
}) => {
|
|
39
|
+
const wrapperRef = react.useRef(null);
|
|
40
|
+
const trailCanvasRef = react.useRef(null);
|
|
41
|
+
const dropContainerRef = react.useRef(null);
|
|
42
|
+
const dropsRef = react.useRef([]);
|
|
43
|
+
const nodeMapRef = react.useRef(/* @__PURE__ */ new Map());
|
|
44
|
+
const rafRef = react.useRef(0);
|
|
45
|
+
const filterIdRef = react.useRef(`rnf-${Math.random().toString(36).slice(2, 7)}`);
|
|
46
|
+
react.useEffect(() => {
|
|
47
|
+
const wrapper = wrapperRef.current;
|
|
48
|
+
const trailCanvas = trailCanvasRef.current;
|
|
49
|
+
const dropContainer = dropContainerRef.current;
|
|
50
|
+
if (!wrapper || !trailCanvas || !dropContainer) return;
|
|
51
|
+
const trailCtx = trailCanvas.getContext("2d");
|
|
52
|
+
if (!trailCtx) return;
|
|
53
|
+
const filterId2 = filterIdRef.current;
|
|
54
|
+
const resize = () => {
|
|
55
|
+
const w = wrapper.offsetWidth;
|
|
56
|
+
const h = wrapper.offsetHeight;
|
|
57
|
+
trailCanvas.width = w;
|
|
58
|
+
trailCanvas.height = h;
|
|
59
|
+
dropsRef.current = Array.from(
|
|
60
|
+
{ length: dropCount },
|
|
61
|
+
() => createStaticDrop(w, h)
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
resize();
|
|
65
|
+
const ro = new ResizeObserver(resize);
|
|
66
|
+
ro.observe(wrapper);
|
|
67
|
+
function getOrCreateNode(drop) {
|
|
68
|
+
let node = nodeMapRef.current.get(drop.id);
|
|
69
|
+
if (!node) {
|
|
70
|
+
node = document.createElement("div");
|
|
71
|
+
node.style.cssText = `
|
|
72
|
+
position: absolute;
|
|
73
|
+
backdrop-filter: url(#${filterId2}) brightness(1.12);
|
|
74
|
+
-webkit-backdrop-filter: url(#${filterId2}) brightness(1.12);
|
|
75
|
+
box-shadow:
|
|
76
|
+
inset 0 0 0 1px rgba(255,255,255,0.4),
|
|
77
|
+
inset -2px -3px 6px rgba(255,255,255,0.18),
|
|
78
|
+
inset 2px 2px 4px rgba(0, 40, 120, 0.15);
|
|
79
|
+
background: radial-gradient(
|
|
80
|
+
circle at 32% 30%,
|
|
81
|
+
rgba(255,255,255,0.30) 0%,
|
|
82
|
+
rgba(255,255,255,0.05) 45%,
|
|
83
|
+
transparent 65%
|
|
84
|
+
);
|
|
85
|
+
pointer-events: none;
|
|
86
|
+
will-change: transform;
|
|
87
|
+
`;
|
|
88
|
+
dropContainer.appendChild(node);
|
|
89
|
+
nodeMapRef.current.set(drop.id, node);
|
|
90
|
+
}
|
|
91
|
+
return node;
|
|
92
|
+
}
|
|
93
|
+
function removeNode(id) {
|
|
94
|
+
const node = nodeMapRef.current.get(id);
|
|
95
|
+
if (node) {
|
|
96
|
+
node.remove();
|
|
97
|
+
nodeMapRef.current.delete(id);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function syncNode(drop) {
|
|
101
|
+
const node = getOrCreateNode(drop);
|
|
102
|
+
const isSliding = drop.kind === "sliding";
|
|
103
|
+
const h = isSliding ? drop.radius * 2.4 : drop.radius * 2;
|
|
104
|
+
const br = isSliding ? "50% 50% 55% 55%" : "50%";
|
|
105
|
+
node.style.left = `${drop.x - drop.radius}px`;
|
|
106
|
+
node.style.top = `${drop.y - drop.radius}px`;
|
|
107
|
+
node.style.width = `${drop.radius * 2}px`;
|
|
108
|
+
node.style.height = `${h}px`;
|
|
109
|
+
node.style.borderRadius = br;
|
|
110
|
+
}
|
|
111
|
+
const tick = () => {
|
|
112
|
+
const { width, height } = trailCanvas;
|
|
113
|
+
trailCtx.fillStyle = "rgba(0,0,0,0.04)";
|
|
114
|
+
trailCtx.fillRect(0, 0, width, height);
|
|
115
|
+
const next = [];
|
|
116
|
+
for (const drop of dropsRef.current) {
|
|
117
|
+
if (drop.kind === "static") {
|
|
118
|
+
drop.age++;
|
|
119
|
+
syncNode(drop);
|
|
120
|
+
if (drop.age >= drop.maxAge) {
|
|
121
|
+
removeNode(drop.id);
|
|
122
|
+
next.push({
|
|
123
|
+
...drop,
|
|
124
|
+
id: _nextId++,
|
|
125
|
+
kind: "sliding",
|
|
126
|
+
speed: randomBetween(1.5, 3.5),
|
|
127
|
+
trail: []
|
|
128
|
+
});
|
|
129
|
+
} else {
|
|
130
|
+
next.push(drop);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
drop.trail.push({ x: drop.x, y: drop.y });
|
|
134
|
+
if (drop.trail.length > 24) drop.trail.shift();
|
|
135
|
+
if (drop.trail.length > 1) {
|
|
136
|
+
trailCtx.beginPath();
|
|
137
|
+
trailCtx.moveTo(drop.trail[0].x, drop.trail[0].y);
|
|
138
|
+
for (let i = 1; i < drop.trail.length; i++) {
|
|
139
|
+
trailCtx.lineTo(drop.trail[i].x, drop.trail[i].y);
|
|
140
|
+
}
|
|
141
|
+
trailCtx.strokeStyle = "rgba(160, 200, 255, 0.18)";
|
|
142
|
+
trailCtx.lineWidth = drop.radius * 0.7;
|
|
143
|
+
trailCtx.lineCap = "round";
|
|
144
|
+
trailCtx.stroke();
|
|
145
|
+
}
|
|
146
|
+
drop.y += drop.speed;
|
|
147
|
+
drop.speed += 0.06;
|
|
148
|
+
syncNode(drop);
|
|
149
|
+
if (drop.y - drop.radius > height) {
|
|
150
|
+
removeNode(drop.id);
|
|
151
|
+
next.push(createStaticDrop(width, height));
|
|
152
|
+
} else {
|
|
153
|
+
next.push(drop);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
dropsRef.current = next;
|
|
158
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
159
|
+
};
|
|
160
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
161
|
+
return () => {
|
|
162
|
+
cancelAnimationFrame(rafRef.current);
|
|
163
|
+
ro.disconnect();
|
|
164
|
+
nodeMapRef.current.forEach((node) => node.remove());
|
|
165
|
+
nodeMapRef.current.clear();
|
|
166
|
+
};
|
|
167
|
+
}, [dropCount]);
|
|
168
|
+
const filterId = filterIdRef.current;
|
|
169
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
ref: wrapperRef,
|
|
173
|
+
className: [RainCanvas_module_default.wrapper, className ?? ""].filter(Boolean).join(" "),
|
|
174
|
+
style: { background, ...style },
|
|
175
|
+
children: [
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "0", height: "0", style: { position: "absolute" }, children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
177
|
+
"filter",
|
|
178
|
+
{
|
|
179
|
+
id: filterId,
|
|
180
|
+
x: "-20%",
|
|
181
|
+
y: "-20%",
|
|
182
|
+
width: "140%",
|
|
183
|
+
height: "140%",
|
|
184
|
+
colorInterpolationFilters: "sRGB",
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
187
|
+
"feTurbulence",
|
|
188
|
+
{
|
|
189
|
+
type: "turbulence",
|
|
190
|
+
baseFrequency: "0.07 0.04",
|
|
191
|
+
numOctaves: "2",
|
|
192
|
+
result: "noise",
|
|
193
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
194
|
+
"animate",
|
|
195
|
+
{
|
|
196
|
+
attributeName: "seed",
|
|
197
|
+
values: "1;20;1",
|
|
198
|
+
dur: "5s",
|
|
199
|
+
repeatCount: "indefinite"
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
205
|
+
"feDisplacementMap",
|
|
206
|
+
{
|
|
207
|
+
in: "SourceGraphic",
|
|
208
|
+
in2: "noise",
|
|
209
|
+
scale: "22",
|
|
210
|
+
xChannelSelector: "R",
|
|
211
|
+
yChannelSelector: "G"
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
) }) }),
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: trailCanvasRef, className: RainCanvas_module_default.trailCanvas }),
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: RainCanvas_module_default.content, children }),
|
|
219
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: dropContainerRef, className: RainCanvas_module_default.dropContainer })
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
exports.RainCanvas = RainCanvas;
|
|
226
|
+
//# sourceMappingURL=index.cjs.map
|
|
227
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/RainCanvas/RainCanvas.module.scss","../../../src/components/RainCanvas/RainCanvas.tsx"],"names":["wrapper","trailCanvas","content","dropContainer","useRef","useEffect","filterId","jsxs","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["@charset \"UTF-8\";\n.wrapper {\n position: relative;\n overflow: hidden;\n width: 100%;\n height: 100%;\n}\n\n/* Scie umide — sotto il contenuto */\n.trailCanvas {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n display: block;\n z-index: 1;\n pointer-events: none;\n}\n\n/* Form e contenuto — sopra le scie */\n.content {\n position: absolute;\n inset: 0;\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Le gocce DOM stanno sopra tutto, ma pointer-events: none (impostato inline) */\n.dropContainer {\n position: absolute;\n inset: 0;\n z-index: 3;\n}\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlJhaW5DYW52YXMubW9kdWxlLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0FBQ0E7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7QUFDQTtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7QUFDQTtFQUNFO0VBQ0E7RUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi53cmFwcGVyIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xufVxuXG4vKiBTY2llIHVtaWRlIOKAlCBzb3R0byBpbCBjb250ZW51dG8gKi9cbi50cmFpbENhbnZhcyB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgaW5zZXQ6IDA7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICB6LWluZGV4OiAxO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLyogRm9ybSBlIGNvbnRlbnV0byDigJQgc29wcmEgbGUgc2NpZSAqL1xuLmNvbnRlbnQge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIGluc2V0OiAwO1xuICB6LWluZGV4OiAyO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbn1cblxuLyogTGUgZ29jY2UgRE9NIHN0YW5ubyBzb3ByYSB0dXR0bywgbWEgcG9pbnRlci1ldmVudHM6IG5vbmUgKGltcG9zdGF0byBpbmxpbmUpICovXG4uZHJvcENvbnRhaW5lciB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgaW5zZXQ6IDA7XG4gIHotaW5kZXg6IDM7XG59XG4iXX0= */","import React, { useEffect, useRef } from \"react\";\nimport styles from \"./RainCanvas.module.scss\";\n\n// --- Tipi ---\n\ninterface Drop {\n id: number;\n kind: \"static\" | \"sliding\";\n x: number;\n y: number;\n radius: number;\n age: number;\n maxAge: number;\n speed: number;\n trail: { x: number; y: number }[];\n}\n\n// --- Helpers ---\n\nlet _nextId = 0;\n\nfunction randomBetween(a: number, b: number) {\n return a + Math.random() * (b - a);\n}\n\nfunction createStaticDrop(width: number, height: number): Drop {\n return {\n id: _nextId++,\n kind: \"static\",\n x: randomBetween(10, width - 10),\n y: randomBetween(10, height - 10),\n radius: randomBetween(4, 11),\n age: 0,\n maxAge: randomBetween(120, 400),\n speed: 0,\n trail: [],\n };\n}\n\n// --- Componente ---\n\nexport interface RainCanvasProps {\n dropCount?: number;\n background?: string;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const RainCanvas: React.FC<RainCanvasProps> = ({\n dropCount = 55,\n background = \"linear-gradient(160deg, #0f172a 0%, #1e3a5f 60%, #0f2a4a 100%)\",\n children,\n className,\n style,\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const trailCanvasRef = useRef<HTMLCanvasElement>(null);\n const dropContainerRef = useRef<HTMLDivElement>(null);\n const dropsRef = useRef<Drop[]>([]);\n const nodeMapRef = useRef<Map<number, HTMLDivElement>>(new Map());\n const rafRef = useRef<number>(0);\n // Unique id per istanza per evitare conflitti se ci sono più RainCanvas nella pagina\n const filterIdRef = useRef(`rnf-${Math.random().toString(36).slice(2, 7)}`);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n const trailCanvas = trailCanvasRef.current;\n const dropContainer = dropContainerRef.current;\n if (!wrapper || !trailCanvas || !dropContainer) return;\n\n const trailCtx = trailCanvas.getContext(\"2d\");\n if (!trailCtx) return;\n\n const filterId = filterIdRef.current;\n\n const resize = () => {\n const w = wrapper.offsetWidth;\n const h = wrapper.offsetHeight;\n trailCanvas.width = w;\n trailCanvas.height = h;\n dropsRef.current = Array.from({ length: dropCount }, () =>\n createStaticDrop(w, h)\n );\n };\n\n resize();\n const ro = new ResizeObserver(resize);\n ro.observe(wrapper);\n\n // Crea un nodo DOM per una goccia e lo aggiunge al container\n function getOrCreateNode(drop: Drop): HTMLDivElement {\n let node = nodeMapRef.current.get(drop.id);\n if (!node) {\n node = document.createElement(\"div\");\n // backdrop-filter: url(#id) applica il filtro SVG al contenuto DOM sottostante\n // Questo è ciò che crea la vera distorsione del contenuto reale\n node.style.cssText = `\n position: absolute;\n backdrop-filter: url(#${filterId}) brightness(1.12);\n -webkit-backdrop-filter: url(#${filterId}) brightness(1.12);\n box-shadow:\n inset 0 0 0 1px rgba(255,255,255,0.4),\n inset -2px -3px 6px rgba(255,255,255,0.18),\n inset 2px 2px 4px rgba(0, 40, 120, 0.15);\n background: radial-gradient(\n circle at 32% 30%,\n rgba(255,255,255,0.30) 0%,\n rgba(255,255,255,0.05) 45%,\n transparent 65%\n );\n pointer-events: none;\n will-change: transform;\n `;\n dropContainer!.appendChild(node);\n nodeMapRef.current.set(drop.id, node);\n }\n return node;\n }\n\n function removeNode(id: number) {\n const node = nodeMapRef.current.get(id);\n if (node) {\n node.remove();\n nodeMapRef.current.delete(id);\n }\n }\n\n function syncNode(drop: Drop) {\n const node = getOrCreateNode(drop);\n const isSliding = drop.kind === \"sliding\";\n const h = isSliding ? drop.radius * 2.4 : drop.radius * 2;\n const br = isSliding ? \"50% 50% 55% 55%\" : \"50%\";\n node.style.left = `${drop.x - drop.radius}px`;\n node.style.top = `${drop.y - drop.radius}px`;\n node.style.width = `${drop.radius * 2}px`;\n node.style.height = `${h}px`;\n node.style.borderRadius = br;\n }\n\n const tick = () => {\n const { width, height } = trailCanvas;\n\n // Fade della scia: riempiamo con un nero semi-trasparente ogni frame\n trailCtx.fillStyle = \"rgba(0,0,0,0.04)\";\n trailCtx.fillRect(0, 0, width, height);\n\n const next: Drop[] = [];\n\n for (const drop of dropsRef.current) {\n if (drop.kind === \"static\") {\n drop.age++;\n syncNode(drop);\n\n if (drop.age >= drop.maxAge) {\n // Diventa scorrevole: rimuovo il vecchio nodo e creo uno nuovo\n removeNode(drop.id);\n next.push({\n ...drop,\n id: _nextId++,\n kind: \"sliding\",\n speed: randomBetween(1.5, 3.5),\n trail: [],\n });\n } else {\n next.push(drop);\n }\n } else {\n // Aggiorna scia\n drop.trail.push({ x: drop.x, y: drop.y });\n if (drop.trail.length > 24) drop.trail.shift();\n\n // Disegna scia umida sul canvas\n if (drop.trail.length > 1) {\n trailCtx.beginPath();\n trailCtx.moveTo(drop.trail[0].x, drop.trail[0].y);\n for (let i = 1; i < drop.trail.length; i++) {\n trailCtx.lineTo(drop.trail[i].x, drop.trail[i].y);\n }\n trailCtx.strokeStyle = \"rgba(160, 200, 255, 0.18)\";\n trailCtx.lineWidth = drop.radius * 0.7;\n trailCtx.lineCap = \"round\";\n trailCtx.stroke();\n }\n\n drop.y += drop.speed;\n drop.speed += 0.06;\n syncNode(drop);\n\n if (drop.y - drop.radius > height) {\n removeNode(drop.id);\n next.push(createStaticDrop(width, height));\n } else {\n next.push(drop);\n }\n }\n }\n\n dropsRef.current = next;\n rafRef.current = requestAnimationFrame(tick);\n };\n\n rafRef.current = requestAnimationFrame(tick);\n\n return () => {\n cancelAnimationFrame(rafRef.current);\n ro.disconnect();\n // Pulizia nodi DOM\n nodeMapRef.current.forEach((node) => node.remove());\n nodeMapRef.current.clear();\n };\n }, [dropCount]);\n\n const filterId = filterIdRef.current;\n\n return (\n <div\n ref={wrapperRef}\n className={[styles.wrapper, className ?? \"\"].filter(Boolean).join(\" \")}\n style={{ background, ...style }}\n >\n {/*\n Definizione del filtro SVG:\n - feTurbulence genera rumore procedurale (pattern d'acqua)\n - feDisplacementMap usa quel rumore per spostare i pixel del backdrop\n L'animazione del seed fa \"muovere\" l'acqua nel tempo\n */}\n <svg width=\"0\" height=\"0\" style={{ position: \"absolute\" }}>\n <defs>\n <filter\n id={filterId}\n x=\"-20%\"\n y=\"-20%\"\n width=\"140%\"\n height=\"140%\"\n colorInterpolationFilters=\"sRGB\"\n >\n <feTurbulence\n type=\"turbulence\"\n baseFrequency=\"0.07 0.04\"\n numOctaves=\"2\"\n result=\"noise\"\n >\n <animate\n attributeName=\"seed\"\n values=\"1;20;1\"\n dur=\"5s\"\n repeatCount=\"indefinite\"\n />\n </feTurbulence>\n <feDisplacementMap\n in=\"SourceGraphic\"\n in2=\"noise\"\n scale=\"22\"\n xChannelSelector=\"R\"\n yChannelSelector=\"G\"\n />\n </filter>\n </defs>\n </svg>\n\n {/* Canvas per le scie umide (z-index basso) */}\n <canvas ref={trailCanvasRef} className={styles.trailCanvas} />\n\n {/* Contenuto (form, ecc.) */}\n <div className={styles.content}>{children}</div>\n\n {/* Container delle gocce DOM — sopra il contenuto, pointer-events none */}\n <div ref={dropContainerRef} className={styles.dropContainer} />\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
/* src/components/RainCanvas/RainCanvas.module.scss */
|
|
4
|
+
.RainCanvas_module_wrapper2 {
|
|
5
|
+
position: relative;
|
|
6
|
+
overflow: hidden;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
}
|
|
10
|
+
.RainCanvas_module_trailCanvas2 {
|
|
11
|
+
position: absolute;
|
|
12
|
+
inset: 0;
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
display: block;
|
|
16
|
+
z-index: 1;
|
|
17
|
+
pointer-events: none;
|
|
18
|
+
}
|
|
19
|
+
.RainCanvas_module_content2 {
|
|
20
|
+
position: absolute;
|
|
21
|
+
inset: 0;
|
|
22
|
+
z-index: 2;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
}
|
|
27
|
+
.RainCanvas_module_dropContainer2 {
|
|
28
|
+
position: absolute;
|
|
29
|
+
inset: 0;
|
|
30
|
+
z-index: 3;
|
|
31
|
+
}
|
|
32
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/RainCanvas/RainCanvas.module.scss"],"sourcesContent":[".wrapper {\n position: relative;\n overflow: hidden;\n width: 100%;\n height: 100%;\n}\n\n/* Scie umide — sotto il contenuto */\n.trailCanvas {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n display: block;\n z-index: 1;\n pointer-events: none;\n}\n\n/* Form e contenuto — sopra le scie */\n.content {\n position: absolute;\n inset: 0;\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Le gocce DOM stanno sopra tutto, ma pointer-events: none (impostato inline) */\n.dropContainer {\n position: absolute;\n inset: 0;\n z-index: 3;\n}\n"],"mappings":";;;AAAA,CAAAA;AACE,YAAA;AACA,YAAA;AACA,SAAA;AACA,UAAA;;AAIF,CAAAC;AACE,YAAA;AACA,SAAA;AACA,SAAA;AACA,UAAA;AACA,WAAA;AACA,WAAA;AACA,kBAAA;;AAIF,CAAAC;AACE,YAAA;AACA,SAAA;AACA,WAAA;AACA,WAAA;AACA,eAAA;AACA,mBAAA;;AAIF,CAAAC;AACE,YAAA;AACA,SAAA;AACA,WAAA;;","names":["wrapper","trailCanvas","content","dropContainer"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface RainCanvasProps {
|
|
4
|
+
dropCount?: number;
|
|
5
|
+
background?: string;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
style?: React.CSSProperties;
|
|
9
|
+
}
|
|
10
|
+
declare const RainCanvas: React.FC<RainCanvasProps>;
|
|
11
|
+
|
|
12
|
+
export { RainCanvas, type RainCanvasProps };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface RainCanvasProps {
|
|
4
|
+
dropCount?: number;
|
|
5
|
+
background?: string;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
style?: React.CSSProperties;
|
|
9
|
+
}
|
|
10
|
+
declare const RainCanvas: React.FC<RainCanvasProps>;
|
|
11
|
+
|
|
12
|
+
export { RainCanvas, type RainCanvasProps };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// src/components/RainCanvas/RainCanvas.tsx
|
|
5
|
+
|
|
6
|
+
// src/components/RainCanvas/RainCanvas.module.scss
|
|
7
|
+
var RainCanvas_module_default = {
|
|
8
|
+
wrapper: "RainCanvas_module_wrapper2",
|
|
9
|
+
trailCanvas: "RainCanvas_module_trailCanvas2",
|
|
10
|
+
content: "RainCanvas_module_content2",
|
|
11
|
+
dropContainer: "RainCanvas_module_dropContainer2"
|
|
12
|
+
};
|
|
13
|
+
var _nextId = 0;
|
|
14
|
+
function randomBetween(a, b) {
|
|
15
|
+
return a + Math.random() * (b - a);
|
|
16
|
+
}
|
|
17
|
+
function createStaticDrop(width, height) {
|
|
18
|
+
return {
|
|
19
|
+
id: _nextId++,
|
|
20
|
+
kind: "static",
|
|
21
|
+
x: randomBetween(10, width - 10),
|
|
22
|
+
y: randomBetween(10, height - 10),
|
|
23
|
+
radius: randomBetween(4, 11),
|
|
24
|
+
age: 0,
|
|
25
|
+
maxAge: randomBetween(120, 400),
|
|
26
|
+
speed: 0,
|
|
27
|
+
trail: []
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var RainCanvas = ({
|
|
31
|
+
dropCount = 55,
|
|
32
|
+
background = "linear-gradient(160deg, #0f172a 0%, #1e3a5f 60%, #0f2a4a 100%)",
|
|
33
|
+
children,
|
|
34
|
+
className,
|
|
35
|
+
style
|
|
36
|
+
}) => {
|
|
37
|
+
const wrapperRef = useRef(null);
|
|
38
|
+
const trailCanvasRef = useRef(null);
|
|
39
|
+
const dropContainerRef = useRef(null);
|
|
40
|
+
const dropsRef = useRef([]);
|
|
41
|
+
const nodeMapRef = useRef(/* @__PURE__ */ new Map());
|
|
42
|
+
const rafRef = useRef(0);
|
|
43
|
+
const filterIdRef = useRef(`rnf-${Math.random().toString(36).slice(2, 7)}`);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const wrapper = wrapperRef.current;
|
|
46
|
+
const trailCanvas = trailCanvasRef.current;
|
|
47
|
+
const dropContainer = dropContainerRef.current;
|
|
48
|
+
if (!wrapper || !trailCanvas || !dropContainer) return;
|
|
49
|
+
const trailCtx = trailCanvas.getContext("2d");
|
|
50
|
+
if (!trailCtx) return;
|
|
51
|
+
const filterId2 = filterIdRef.current;
|
|
52
|
+
const resize = () => {
|
|
53
|
+
const w = wrapper.offsetWidth;
|
|
54
|
+
const h = wrapper.offsetHeight;
|
|
55
|
+
trailCanvas.width = w;
|
|
56
|
+
trailCanvas.height = h;
|
|
57
|
+
dropsRef.current = Array.from(
|
|
58
|
+
{ length: dropCount },
|
|
59
|
+
() => createStaticDrop(w, h)
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
resize();
|
|
63
|
+
const ro = new ResizeObserver(resize);
|
|
64
|
+
ro.observe(wrapper);
|
|
65
|
+
function getOrCreateNode(drop) {
|
|
66
|
+
let node = nodeMapRef.current.get(drop.id);
|
|
67
|
+
if (!node) {
|
|
68
|
+
node = document.createElement("div");
|
|
69
|
+
node.style.cssText = `
|
|
70
|
+
position: absolute;
|
|
71
|
+
backdrop-filter: url(#${filterId2}) brightness(1.12);
|
|
72
|
+
-webkit-backdrop-filter: url(#${filterId2}) brightness(1.12);
|
|
73
|
+
box-shadow:
|
|
74
|
+
inset 0 0 0 1px rgba(255,255,255,0.4),
|
|
75
|
+
inset -2px -3px 6px rgba(255,255,255,0.18),
|
|
76
|
+
inset 2px 2px 4px rgba(0, 40, 120, 0.15);
|
|
77
|
+
background: radial-gradient(
|
|
78
|
+
circle at 32% 30%,
|
|
79
|
+
rgba(255,255,255,0.30) 0%,
|
|
80
|
+
rgba(255,255,255,0.05) 45%,
|
|
81
|
+
transparent 65%
|
|
82
|
+
);
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
will-change: transform;
|
|
85
|
+
`;
|
|
86
|
+
dropContainer.appendChild(node);
|
|
87
|
+
nodeMapRef.current.set(drop.id, node);
|
|
88
|
+
}
|
|
89
|
+
return node;
|
|
90
|
+
}
|
|
91
|
+
function removeNode(id) {
|
|
92
|
+
const node = nodeMapRef.current.get(id);
|
|
93
|
+
if (node) {
|
|
94
|
+
node.remove();
|
|
95
|
+
nodeMapRef.current.delete(id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function syncNode(drop) {
|
|
99
|
+
const node = getOrCreateNode(drop);
|
|
100
|
+
const isSliding = drop.kind === "sliding";
|
|
101
|
+
const h = isSliding ? drop.radius * 2.4 : drop.radius * 2;
|
|
102
|
+
const br = isSliding ? "50% 50% 55% 55%" : "50%";
|
|
103
|
+
node.style.left = `${drop.x - drop.radius}px`;
|
|
104
|
+
node.style.top = `${drop.y - drop.radius}px`;
|
|
105
|
+
node.style.width = `${drop.radius * 2}px`;
|
|
106
|
+
node.style.height = `${h}px`;
|
|
107
|
+
node.style.borderRadius = br;
|
|
108
|
+
}
|
|
109
|
+
const tick = () => {
|
|
110
|
+
const { width, height } = trailCanvas;
|
|
111
|
+
trailCtx.fillStyle = "rgba(0,0,0,0.04)";
|
|
112
|
+
trailCtx.fillRect(0, 0, width, height);
|
|
113
|
+
const next = [];
|
|
114
|
+
for (const drop of dropsRef.current) {
|
|
115
|
+
if (drop.kind === "static") {
|
|
116
|
+
drop.age++;
|
|
117
|
+
syncNode(drop);
|
|
118
|
+
if (drop.age >= drop.maxAge) {
|
|
119
|
+
removeNode(drop.id);
|
|
120
|
+
next.push({
|
|
121
|
+
...drop,
|
|
122
|
+
id: _nextId++,
|
|
123
|
+
kind: "sliding",
|
|
124
|
+
speed: randomBetween(1.5, 3.5),
|
|
125
|
+
trail: []
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
next.push(drop);
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
drop.trail.push({ x: drop.x, y: drop.y });
|
|
132
|
+
if (drop.trail.length > 24) drop.trail.shift();
|
|
133
|
+
if (drop.trail.length > 1) {
|
|
134
|
+
trailCtx.beginPath();
|
|
135
|
+
trailCtx.moveTo(drop.trail[0].x, drop.trail[0].y);
|
|
136
|
+
for (let i = 1; i < drop.trail.length; i++) {
|
|
137
|
+
trailCtx.lineTo(drop.trail[i].x, drop.trail[i].y);
|
|
138
|
+
}
|
|
139
|
+
trailCtx.strokeStyle = "rgba(160, 200, 255, 0.18)";
|
|
140
|
+
trailCtx.lineWidth = drop.radius * 0.7;
|
|
141
|
+
trailCtx.lineCap = "round";
|
|
142
|
+
trailCtx.stroke();
|
|
143
|
+
}
|
|
144
|
+
drop.y += drop.speed;
|
|
145
|
+
drop.speed += 0.06;
|
|
146
|
+
syncNode(drop);
|
|
147
|
+
if (drop.y - drop.radius > height) {
|
|
148
|
+
removeNode(drop.id);
|
|
149
|
+
next.push(createStaticDrop(width, height));
|
|
150
|
+
} else {
|
|
151
|
+
next.push(drop);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
dropsRef.current = next;
|
|
156
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
157
|
+
};
|
|
158
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
159
|
+
return () => {
|
|
160
|
+
cancelAnimationFrame(rafRef.current);
|
|
161
|
+
ro.disconnect();
|
|
162
|
+
nodeMapRef.current.forEach((node) => node.remove());
|
|
163
|
+
nodeMapRef.current.clear();
|
|
164
|
+
};
|
|
165
|
+
}, [dropCount]);
|
|
166
|
+
const filterId = filterIdRef.current;
|
|
167
|
+
return /* @__PURE__ */ jsxs(
|
|
168
|
+
"div",
|
|
169
|
+
{
|
|
170
|
+
ref: wrapperRef,
|
|
171
|
+
className: [RainCanvas_module_default.wrapper, className ?? ""].filter(Boolean).join(" "),
|
|
172
|
+
style: { background, ...style },
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsx("svg", { width: "0", height: "0", style: { position: "absolute" }, children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
|
|
175
|
+
"filter",
|
|
176
|
+
{
|
|
177
|
+
id: filterId,
|
|
178
|
+
x: "-20%",
|
|
179
|
+
y: "-20%",
|
|
180
|
+
width: "140%",
|
|
181
|
+
height: "140%",
|
|
182
|
+
colorInterpolationFilters: "sRGB",
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ jsx(
|
|
185
|
+
"feTurbulence",
|
|
186
|
+
{
|
|
187
|
+
type: "turbulence",
|
|
188
|
+
baseFrequency: "0.07 0.04",
|
|
189
|
+
numOctaves: "2",
|
|
190
|
+
result: "noise",
|
|
191
|
+
children: /* @__PURE__ */ jsx(
|
|
192
|
+
"animate",
|
|
193
|
+
{
|
|
194
|
+
attributeName: "seed",
|
|
195
|
+
values: "1;20;1",
|
|
196
|
+
dur: "5s",
|
|
197
|
+
repeatCount: "indefinite"
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
),
|
|
202
|
+
/* @__PURE__ */ jsx(
|
|
203
|
+
"feDisplacementMap",
|
|
204
|
+
{
|
|
205
|
+
in: "SourceGraphic",
|
|
206
|
+
in2: "noise",
|
|
207
|
+
scale: "22",
|
|
208
|
+
xChannelSelector: "R",
|
|
209
|
+
yChannelSelector: "G"
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
) }) }),
|
|
215
|
+
/* @__PURE__ */ jsx("canvas", { ref: trailCanvasRef, className: RainCanvas_module_default.trailCanvas }),
|
|
216
|
+
/* @__PURE__ */ jsx("div", { className: RainCanvas_module_default.content, children }),
|
|
217
|
+
/* @__PURE__ */ jsx("div", { ref: dropContainerRef, className: RainCanvas_module_default.dropContainer })
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export { RainCanvas };
|
|
224
|
+
//# sourceMappingURL=index.js.map
|
|
225
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/RainCanvas/RainCanvas.module.scss","../../../src/components/RainCanvas/RainCanvas.tsx"],"names":["wrapper","trailCanvas","content","dropContainer","filterId"],"mappings":"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","file":"index.js","sourcesContent":["@charset \"UTF-8\";\n.wrapper {\n position: relative;\n overflow: hidden;\n width: 100%;\n height: 100%;\n}\n\n/* Scie umide — sotto il contenuto */\n.trailCanvas {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n display: block;\n z-index: 1;\n pointer-events: none;\n}\n\n/* Form e contenuto — sopra le scie */\n.content {\n position: absolute;\n inset: 0;\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Le gocce DOM stanno sopra tutto, ma pointer-events: none (impostato inline) */\n.dropContainer {\n position: absolute;\n inset: 0;\n z-index: 3;\n}\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlJhaW5DYW52YXMubW9kdWxlLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0FBQ0E7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7QUFDQTtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7QUFDQTtFQUNFO0VBQ0E7RUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi53cmFwcGVyIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xufVxuXG4vKiBTY2llIHVtaWRlIOKAlCBzb3R0byBpbCBjb250ZW51dG8gKi9cbi50cmFpbENhbnZhcyB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgaW5zZXQ6IDA7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICB6LWluZGV4OiAxO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLyogRm9ybSBlIGNvbnRlbnV0byDigJQgc29wcmEgbGUgc2NpZSAqL1xuLmNvbnRlbnQge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIGluc2V0OiAwO1xuICB6LWluZGV4OiAyO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbn1cblxuLyogTGUgZ29jY2UgRE9NIHN0YW5ubyBzb3ByYSB0dXR0bywgbWEgcG9pbnRlci1ldmVudHM6IG5vbmUgKGltcG9zdGF0byBpbmxpbmUpICovXG4uZHJvcENvbnRhaW5lciB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgaW5zZXQ6IDA7XG4gIHotaW5kZXg6IDM7XG59XG4iXX0= */","import React, { useEffect, useRef } from \"react\";\nimport styles from \"./RainCanvas.module.scss\";\n\n// --- Tipi ---\n\ninterface Drop {\n id: number;\n kind: \"static\" | \"sliding\";\n x: number;\n y: number;\n radius: number;\n age: number;\n maxAge: number;\n speed: number;\n trail: { x: number; y: number }[];\n}\n\n// --- Helpers ---\n\nlet _nextId = 0;\n\nfunction randomBetween(a: number, b: number) {\n return a + Math.random() * (b - a);\n}\n\nfunction createStaticDrop(width: number, height: number): Drop {\n return {\n id: _nextId++,\n kind: \"static\",\n x: randomBetween(10, width - 10),\n y: randomBetween(10, height - 10),\n radius: randomBetween(4, 11),\n age: 0,\n maxAge: randomBetween(120, 400),\n speed: 0,\n trail: [],\n };\n}\n\n// --- Componente ---\n\nexport interface RainCanvasProps {\n dropCount?: number;\n background?: string;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const RainCanvas: React.FC<RainCanvasProps> = ({\n dropCount = 55,\n background = \"linear-gradient(160deg, #0f172a 0%, #1e3a5f 60%, #0f2a4a 100%)\",\n children,\n className,\n style,\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const trailCanvasRef = useRef<HTMLCanvasElement>(null);\n const dropContainerRef = useRef<HTMLDivElement>(null);\n const dropsRef = useRef<Drop[]>([]);\n const nodeMapRef = useRef<Map<number, HTMLDivElement>>(new Map());\n const rafRef = useRef<number>(0);\n // Unique id per istanza per evitare conflitti se ci sono più RainCanvas nella pagina\n const filterIdRef = useRef(`rnf-${Math.random().toString(36).slice(2, 7)}`);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n const trailCanvas = trailCanvasRef.current;\n const dropContainer = dropContainerRef.current;\n if (!wrapper || !trailCanvas || !dropContainer) return;\n\n const trailCtx = trailCanvas.getContext(\"2d\");\n if (!trailCtx) return;\n\n const filterId = filterIdRef.current;\n\n const resize = () => {\n const w = wrapper.offsetWidth;\n const h = wrapper.offsetHeight;\n trailCanvas.width = w;\n trailCanvas.height = h;\n dropsRef.current = Array.from({ length: dropCount }, () =>\n createStaticDrop(w, h)\n );\n };\n\n resize();\n const ro = new ResizeObserver(resize);\n ro.observe(wrapper);\n\n // Crea un nodo DOM per una goccia e lo aggiunge al container\n function getOrCreateNode(drop: Drop): HTMLDivElement {\n let node = nodeMapRef.current.get(drop.id);\n if (!node) {\n node = document.createElement(\"div\");\n // backdrop-filter: url(#id) applica il filtro SVG al contenuto DOM sottostante\n // Questo è ciò che crea la vera distorsione del contenuto reale\n node.style.cssText = `\n position: absolute;\n backdrop-filter: url(#${filterId}) brightness(1.12);\n -webkit-backdrop-filter: url(#${filterId}) brightness(1.12);\n box-shadow:\n inset 0 0 0 1px rgba(255,255,255,0.4),\n inset -2px -3px 6px rgba(255,255,255,0.18),\n inset 2px 2px 4px rgba(0, 40, 120, 0.15);\n background: radial-gradient(\n circle at 32% 30%,\n rgba(255,255,255,0.30) 0%,\n rgba(255,255,255,0.05) 45%,\n transparent 65%\n );\n pointer-events: none;\n will-change: transform;\n `;\n dropContainer!.appendChild(node);\n nodeMapRef.current.set(drop.id, node);\n }\n return node;\n }\n\n function removeNode(id: number) {\n const node = nodeMapRef.current.get(id);\n if (node) {\n node.remove();\n nodeMapRef.current.delete(id);\n }\n }\n\n function syncNode(drop: Drop) {\n const node = getOrCreateNode(drop);\n const isSliding = drop.kind === \"sliding\";\n const h = isSliding ? drop.radius * 2.4 : drop.radius * 2;\n const br = isSliding ? \"50% 50% 55% 55%\" : \"50%\";\n node.style.left = `${drop.x - drop.radius}px`;\n node.style.top = `${drop.y - drop.radius}px`;\n node.style.width = `${drop.radius * 2}px`;\n node.style.height = `${h}px`;\n node.style.borderRadius = br;\n }\n\n const tick = () => {\n const { width, height } = trailCanvas;\n\n // Fade della scia: riempiamo con un nero semi-trasparente ogni frame\n trailCtx.fillStyle = \"rgba(0,0,0,0.04)\";\n trailCtx.fillRect(0, 0, width, height);\n\n const next: Drop[] = [];\n\n for (const drop of dropsRef.current) {\n if (drop.kind === \"static\") {\n drop.age++;\n syncNode(drop);\n\n if (drop.age >= drop.maxAge) {\n // Diventa scorrevole: rimuovo il vecchio nodo e creo uno nuovo\n removeNode(drop.id);\n next.push({\n ...drop,\n id: _nextId++,\n kind: \"sliding\",\n speed: randomBetween(1.5, 3.5),\n trail: [],\n });\n } else {\n next.push(drop);\n }\n } else {\n // Aggiorna scia\n drop.trail.push({ x: drop.x, y: drop.y });\n if (drop.trail.length > 24) drop.trail.shift();\n\n // Disegna scia umida sul canvas\n if (drop.trail.length > 1) {\n trailCtx.beginPath();\n trailCtx.moveTo(drop.trail[0].x, drop.trail[0].y);\n for (let i = 1; i < drop.trail.length; i++) {\n trailCtx.lineTo(drop.trail[i].x, drop.trail[i].y);\n }\n trailCtx.strokeStyle = \"rgba(160, 200, 255, 0.18)\";\n trailCtx.lineWidth = drop.radius * 0.7;\n trailCtx.lineCap = \"round\";\n trailCtx.stroke();\n }\n\n drop.y += drop.speed;\n drop.speed += 0.06;\n syncNode(drop);\n\n if (drop.y - drop.radius > height) {\n removeNode(drop.id);\n next.push(createStaticDrop(width, height));\n } else {\n next.push(drop);\n }\n }\n }\n\n dropsRef.current = next;\n rafRef.current = requestAnimationFrame(tick);\n };\n\n rafRef.current = requestAnimationFrame(tick);\n\n return () => {\n cancelAnimationFrame(rafRef.current);\n ro.disconnect();\n // Pulizia nodi DOM\n nodeMapRef.current.forEach((node) => node.remove());\n nodeMapRef.current.clear();\n };\n }, [dropCount]);\n\n const filterId = filterIdRef.current;\n\n return (\n <div\n ref={wrapperRef}\n className={[styles.wrapper, className ?? \"\"].filter(Boolean).join(\" \")}\n style={{ background, ...style }}\n >\n {/*\n Definizione del filtro SVG:\n - feTurbulence genera rumore procedurale (pattern d'acqua)\n - feDisplacementMap usa quel rumore per spostare i pixel del backdrop\n L'animazione del seed fa \"muovere\" l'acqua nel tempo\n */}\n <svg width=\"0\" height=\"0\" style={{ position: \"absolute\" }}>\n <defs>\n <filter\n id={filterId}\n x=\"-20%\"\n y=\"-20%\"\n width=\"140%\"\n height=\"140%\"\n colorInterpolationFilters=\"sRGB\"\n >\n <feTurbulence\n type=\"turbulence\"\n baseFrequency=\"0.07 0.04\"\n numOctaves=\"2\"\n result=\"noise\"\n >\n <animate\n attributeName=\"seed\"\n values=\"1;20;1\"\n dur=\"5s\"\n repeatCount=\"indefinite\"\n />\n </feTurbulence>\n <feDisplacementMap\n in=\"SourceGraphic\"\n in2=\"noise\"\n scale=\"22\"\n xChannelSelector=\"R\"\n yChannelSelector=\"G\"\n />\n </filter>\n </defs>\n </svg>\n\n {/* Canvas per le scie umide (z-index basso) */}\n <canvas ref={trailCanvasRef} className={styles.trailCanvas} />\n\n {/* Contenuto (form, ecc.) */}\n <div className={styles.content}>{children}</div>\n\n {/* Container delle gocce DOM — sopra il contenuto, pointer-events none */}\n <div ref={dropContainerRef} className={styles.dropContainer} />\n </div>\n );\n};\n"]}
|