@protohiro/effects 0.1.2 → 0.2.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 +1 -0
- package/dist/index.cjs +101 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +101 -2
- package/dist/index.js.map +1 -1
- package/package.json +12 -3
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var effectsCore=require('@protohiro/effects-core'),react=require('react');var
|
|
1
|
+
'use strict';var effectsCore=require('@protohiro/effects-core'),react=require('react');var a=`
|
|
2
2
|
.pe-gradient-border {
|
|
3
3
|
position: relative;
|
|
4
4
|
isolation: isolate;
|
|
@@ -65,10 +65,109 @@
|
|
|
65
65
|
pointer-events: none;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
.pe-spotlight {
|
|
69
|
+
position: relative;
|
|
70
|
+
isolation: isolate;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.pe-spotlight::before {
|
|
74
|
+
content: '';
|
|
75
|
+
position: absolute;
|
|
76
|
+
inset: 0;
|
|
77
|
+
border-radius: inherit;
|
|
78
|
+
pointer-events: none;
|
|
79
|
+
opacity: var(--pe-spotlight-intensity, 0.45);
|
|
80
|
+
background:
|
|
81
|
+
radial-gradient(
|
|
82
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
83
|
+
color-mix(
|
|
84
|
+
in srgb,
|
|
85
|
+
var(--pe-spotlight-color, #7dd3fc) calc(var(--pe-spotlight-core-intensity, 0.58) * 100%),
|
|
86
|
+
white
|
|
87
|
+
)
|
|
88
|
+
0%,
|
|
89
|
+
color-mix(
|
|
90
|
+
in srgb,
|
|
91
|
+
var(--pe-spotlight-color, #7dd3fc) calc((0.48 + var(--pe-spotlight-core-intensity, 0.58) * 0.32) * 100%),
|
|
92
|
+
white
|
|
93
|
+
)
|
|
94
|
+
calc(var(--pe-spotlight-size, 180px) * 0.14),
|
|
95
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 38%, transparent) calc(var(--pe-spotlight-size, 180px) * 0.4),
|
|
96
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 20%, transparent) var(--pe-spotlight-size, 180px),
|
|
97
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.45)
|
|
98
|
+
),
|
|
99
|
+
radial-gradient(
|
|
100
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
101
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 16%, transparent) 0%,
|
|
102
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 8%, transparent) calc(var(--pe-spotlight-size, 180px) * 1.2),
|
|
103
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.8)
|
|
104
|
+
);
|
|
105
|
+
mix-blend-mode: screen;
|
|
106
|
+
filter: blur(calc(1px + var(--pe-spotlight-softness, 0.72) * 6px)) saturate(128%);
|
|
107
|
+
transition: background 120ms ease-out, opacity 120ms ease-out;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@supports ((-webkit-mask-image: radial-gradient(white, black)) or (mask-image: radial-gradient(white, black))) {
|
|
111
|
+
.pe-spotlight.pe-spotlight--reveal::before {
|
|
112
|
+
opacity: var(--pe-spotlight-reveal-opacity, 0.92);
|
|
113
|
+
background-image:
|
|
114
|
+
var(
|
|
115
|
+
--pe-spotlight-reveal-image,
|
|
116
|
+
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 220'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%236d28d9'/%3E%3Cstop offset='52%25' stop-color='%230ea5e9'/%3E%3Cstop offset='100%25' stop-color='%2322d3ee'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='320' height='220' fill='url(%23g)'/%3E%3Ccircle cx='86' cy='74' r='52' fill='rgba(255,255,255,0.24)'/%3E%3Ccircle cx='252' cy='154' r='70' fill='rgba(255,255,255,0.14)'/%3E%3C/svg%3E")
|
|
117
|
+
),
|
|
118
|
+
linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));
|
|
119
|
+
background-size: var(--pe-spotlight-reveal-size, cover), cover;
|
|
120
|
+
background-position: center;
|
|
121
|
+
background-repeat: no-repeat;
|
|
122
|
+
mix-blend-mode: normal;
|
|
123
|
+
filter: saturate(120%);
|
|
124
|
+
-webkit-mask-image: radial-gradient(
|
|
125
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
126
|
+
rgba(0, 0, 0, 1) 0,
|
|
127
|
+
rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),
|
|
128
|
+
rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),
|
|
129
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.22)
|
|
130
|
+
);
|
|
131
|
+
mask-image: radial-gradient(
|
|
132
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
133
|
+
rgba(0, 0, 0, 1) 0,
|
|
134
|
+
rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),
|
|
135
|
+
rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),
|
|
136
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.22)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@supports not (color: color-mix(in srgb, white, black)) {
|
|
142
|
+
.pe-spotlight::before {
|
|
143
|
+
background:
|
|
144
|
+
radial-gradient(
|
|
145
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
146
|
+
rgba(255, 255, 255, 0.86) 0%,
|
|
147
|
+
rgba(255, 255, 255, 0.56) calc(var(--pe-spotlight-size, 180px) * 0.14),
|
|
148
|
+
rgba(255, 255, 255, 0.3) calc(var(--pe-spotlight-size, 180px) * 0.4),
|
|
149
|
+
rgba(255, 255, 255, 0.16) var(--pe-spotlight-size, 180px),
|
|
150
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.45)
|
|
151
|
+
),
|
|
152
|
+
radial-gradient(
|
|
153
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
154
|
+
rgba(255, 255, 255, 0.16) 0%,
|
|
155
|
+
rgba(255, 255, 255, 0.08) calc(var(--pe-spotlight-size, 180px) * 1.2),
|
|
156
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.8)
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.pe-spotlight.pe-spotlight--reveal::before {
|
|
161
|
+
background-image:
|
|
162
|
+
var(--pe-spotlight-reveal-image, linear-gradient(135deg, rgba(109, 40, 217, 0.9), rgba(14, 165, 233, 0.95))),
|
|
163
|
+
linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
68
167
|
@media (prefers-reduced-motion: reduce) {
|
|
69
168
|
.pe-noise::after {
|
|
70
169
|
opacity: calc(var(--pe-noise-opacity, 0.28) * 0.9);
|
|
71
170
|
}
|
|
72
171
|
}
|
|
73
|
-
`;function
|
|
172
|
+
`;function i(e){let[t,o]=react.useState(null);return react.useEffect(()=>{if(!t||e.disabled)return;effectsCore.ensureGlobalStyle(e.styleId,e.styleText);let s=[];return s.push(effectsCore.applyEffectClass(t,e.className)),e.userClassName&&s.push(effectsCore.applyEffectClass(t,e.userClassName)),s.push(effectsCore.applyCssVars(t,e.vars)),()=>{for(let l of s.reverse())l();}},[t,e.className,e.userClassName,e.disabled,e.styleId,e.styleText,e.vars]),react.useCallback(s=>{o(s);},[])}var G="protohiro-effects-base";function F(e={}){let t=react.useMemo(()=>({"--pe-gb-thickness":effectsCore.toCssLength(e.thickness),"--pe-gb-radius":effectsCore.toCssLength(e.radius),"--pe-gb-colors":e.colors,"--pe-gb-angle":effectsCore.toCssAngle(e.angle)}),[e.thickness,e.radius,e.colors,e.angle]);return i({className:"pe-gradient-border",userClassName:e.className,vars:t,disabled:e.disabled,styleId:G,styleText:a})}var _="protohiro-effects-base";function B(e={}){let t=react.useMemo(()=>({"--pe-glow-color":e.color,"--pe-glow-blur":effectsCore.toCssLength(e.blur),"--pe-glow-spread":effectsCore.toCssLength(e.spread),"--pe-glow-opacity":effectsCore.toCssNumber(e.opacity)}),[e.color,e.blur,e.spread,e.opacity]);return i({className:"pe-glow",userClassName:e.className,vars:t,disabled:e.disabled,styleId:_,styleText:a})}var W="protohiro-effects-base";function $(e){if(e!==void 0&&!Number.isNaN(e))return Math.max(0,Math.min(1,e))}function A(e={}){let t=$(e.intensity),o=react.useMemo(()=>({"--pe-noise-size":effectsCore.toCssLength(e.size??120),"--pe-noise-opacity":effectsCore.toCssNumber(t??.2)}),[e.size,t]);return i({className:"pe-noise",userClassName:e.className,vars:o,disabled:e.disabled,styleId:W,styleText:a})}var J="protohiro-effects-base";function c(e){if(!(e===void 0||Number.isNaN(e)))return Math.max(0,Math.min(1,e))}function k(e){if(e!==void 0)return typeof e=="number"?`${e}%`:e}function K(e){if(!e)return;let t=e.trim();if(t)return t.startsWith("url(")||t.startsWith("linear-gradient(")||t.startsWith("radial-gradient(")||t.startsWith("conic-gradient(")?t:`url("${t.replace(/"/g,'\\"')}")`}function Q(e){return e===void 0||typeof e!="number"?e:Math.max(0,e)}function Z(e={}){let[t,o]=react.useState(null),s=e.mode==="reveal",l=Q(e.size),g=c(e.intensity),f=c(e.softness),m=c(e.coreIntensity),u=c(e.revealOpacity),b=k(e.x),h=k(e.y),v=K(e.revealImage),x=react.useMemo(()=>({"--pe-spotlight-size":effectsCore.toCssLength(l),"--pe-spotlight-intensity":effectsCore.toCssNumber(g),"--pe-spotlight-color":e.color,"--pe-spotlight-softness":effectsCore.toCssNumber(f),"--pe-spotlight-core-intensity":effectsCore.toCssNumber(m),"--pe-spotlight-x":b,"--pe-spotlight-y":h,"--pe-spotlight-reveal-color":e.revealColor,"--pe-spotlight-reveal-image":v,"--pe-spotlight-reveal-size":effectsCore.toCssLength(e.revealSize),"--pe-spotlight-reveal-opacity":effectsCore.toCssNumber(u)}),[l,g,f,m,e.color,b,h,e.revealColor,v,e.revealSize,u]);return react.useEffect(()=>{if(!t||e.disabled)return;effectsCore.ensureGlobalStyle(J,a);let r=[];return r.push(effectsCore.applyEffectClass(t,"pe-spotlight")),s&&r.push(effectsCore.applyEffectClass(t,"pe-spotlight--reveal")),e.className&&r.push(effectsCore.applyEffectClass(t,e.className)),r.push(effectsCore.applyCssVars(t,x)),()=>{for(let n of r.reverse())n();}},[t,e.disabled,e.className,s,x]),react.useEffect(()=>{if(!t||e.disabled||!e.followPointer)return;let r=n=>{t.style.setProperty("--pe-spotlight-x",`${n.offsetX}px`),t.style.setProperty("--pe-spotlight-y",`${n.offsetY}px`);};return t.addEventListener("pointermove",r),()=>{t.removeEventListener("pointermove",r);}},[t,e.disabled,e.followPointer]),react.useCallback(r=>{o(r);},[])}exports.useGlowEffect=B;exports.useGradientBorderEffect=F;exports.useNoiseEffect=A;exports.useSpotlightEffect=Z;//# sourceMappingURL=index.cjs.map
|
|
74
173
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/effectStyles.ts","../src/shared/useCssEffect.ts","../src/effects/useGradientBorderEffect.ts","../src/effects/useGlowEffect.ts","../src/effects/useNoiseEffect.ts"],"names":["EFFECT_STYLES","useCssEffect","input","node","setNode","useState","useEffect","ensureGlobalStyle","cleanups","applyEffectClass","applyCssVars","cleanup","useCallback","next","STYLE_ID","useGradientBorderEffect","options","vars","useMemo","toCssLength","toCssAngle","useGlowEffect","toCssNumber","clampUnit","value","useNoiseEffect","intensity"],"mappings":"uFAAO,IAAMA,CAAAA,CAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;ACA7B,CAAA,CAYO,SAASC,EAAoCC,CAAAA,CAA0B,CAC5E,GAAM,CAACC,EAAMC,CAAO,CAAA,CAAIC,cAAAA,CAAmB,IAAI,EAE/C,OAAAC,eAAAA,CAAU,IAAM,CACd,GAAI,CAACH,CAAAA,EAAQD,EAAM,QAAA,CACjB,OAGFK,8BAAkBL,CAAAA,CAAM,OAAA,CAASA,CAAAA,CAAM,SAAS,EAEhD,IAAMM,CAAAA,CAA8B,EAAC,CACrC,OAAAA,CAAAA,CAAS,IAAA,CAAKC,4BAAAA,CAAiBN,CAAAA,CAAMD,EAAM,SAAS,CAAC,EAEjDA,CAAAA,CAAM,aAAA,EACRM,EAAS,IAAA,CAAKC,4BAAAA,CAAiBN,CAAAA,CAAMD,CAAAA,CAAM,aAAa,CAAC,CAAA,CAG3DM,EAAS,IAAA,CAAKE,wBAAAA,CAAaP,EAAMD,CAAAA,CAAM,IAAI,CAAC,CAAA,CAErC,IAAM,CACX,IAAA,IAAWS,KAAWH,CAAAA,CAAS,OAAA,GAC7BG,CAAAA,GAEJ,CACF,CAAA,CAAG,CACDR,CAAAA,CACAD,CAAAA,CAAM,SAAA,CACNA,CAAAA,CAAM,cACNA,CAAAA,CAAM,QAAA,CACNA,CAAAA,CAAM,OAAA,CACNA,EAAM,SAAA,CACNA,CAAAA,CAAM,IACR,CAAC,CAAA,CAEMU,kBAAaC,CAAAA,EAAmB,CACrCT,CAAAA,CAAQS,CAAI,EACd,CAAA,CAAG,EAAE,CACP,CC1CA,IAAMC,CAAAA,CAAW,wBAAA,CAEV,SAASC,EACdC,CAAAA,CAAiC,GACjC,CACA,IAAMC,EAAOC,aAAAA,CACX,KAAO,CACL,mBAAA,CAAqBC,wBAAYH,CAAAA,CAAQ,SAAS,CAAA,CAClD,gBAAA,CAAkBG,wBAAYH,CAAAA,CAAQ,MAAM,CAAA,CAC5C,gBAAA,CAAkBA,EAAQ,MAAA,CAC1B,eAAA,CAAiBI,uBAAWJ,CAAAA,CAAQ,KAAK,CAC3C,CAAA,CAAA,CACA,CAACA,CAAAA,CAAQ,SAAA,CAAWA,EAAQ,MAAA,CAAQA,CAAAA,CAAQ,OAAQA,CAAAA,CAAQ,KAAK,CACnE,CAAA,CAEA,OAAOf,CAAAA,CAAgB,CACrB,UAAW,oBAAA,CACX,aAAA,CAAee,EAAQ,SAAA,CACvB,IAAA,CAAAC,EACA,QAAA,CAAUD,CAAAA,CAAQ,QAAA,CAClB,OAAA,CAASF,EACT,SAAA,CAAWd,CACb,CAAC,CACH,CCvBA,IAAMc,CAAAA,CAAW,wBAAA,CAEV,SAASO,CAAAA,CAAmDL,EAAuB,EAAC,CAAG,CAC5F,IAAMC,EAAOC,aAAAA,CACX,KAAO,CACL,iBAAA,CAAmBF,EAAQ,KAAA,CAC3B,gBAAA,CAAkBG,wBAAYH,CAAAA,CAAQ,IAAI,EAC1C,kBAAA,CAAoBG,uBAAAA,CAAYH,CAAAA,CAAQ,MAAM,EAC9C,mBAAA,CAAqBM,uBAAAA,CAAYN,CAAAA,CAAQ,OAAO,CAClD,CAAA,CAAA,CACA,CAACA,CAAAA,CAAQ,KAAA,CAAOA,EAAQ,IAAA,CAAMA,CAAAA,CAAQ,OAAQA,CAAAA,CAAQ,OAAO,CAC/D,CAAA,CAEA,OAAOf,CAAAA,CAAgB,CACrB,UAAW,SAAA,CACX,aAAA,CAAee,EAAQ,SAAA,CACvB,IAAA,CAAAC,EACA,QAAA,CAAUD,CAAAA,CAAQ,QAAA,CAClB,OAAA,CAASF,EACT,SAAA,CAAWd,CACb,CAAC,CACH,CCrBA,IAAMc,CAAAA,CAAW,wBAAA,CAEjB,SAASS,CAAAA,CAAUC,EAA+C,CAChE,GAAIA,IAAU,MAAA,EAIV,CAAA,MAAA,CAAO,MAAMA,CAAK,CAAA,CAItB,OAAO,IAAA,CAAK,IAAI,CAAA,CAAG,IAAA,CAAK,IAAI,CAAA,CAAGA,CAAK,CAAC,CACvC,CAEO,SAASC,CAAAA,CAAoDT,EAAwB,EAAC,CAAG,CAC9F,IAAMU,CAAAA,CAAYH,EAAUP,CAAAA,CAAQ,SAAS,CAAA,CAEvCC,CAAAA,CAAOC,cACX,KAAO,CACL,iBAAA,CAAmBC,uBAAAA,CAAYH,EAAQ,IAAA,EAAQ,GAAG,CAAA,CAClD,oBAAA,CAAsBM,wBAAYI,CAAAA,EAAa,EAAG,CACpD,CAAA,CAAA,CACA,CAACV,EAAQ,IAAA,CAAMU,CAAS,CAC1B,CAAA,CAEA,OAAOzB,CAAAA,CAAgB,CACrB,UAAW,UAAA,CACX,aAAA,CAAee,EAAQ,SAAA,CACvB,IAAA,CAAAC,CAAAA,CACA,QAAA,CAAUD,EAAQ,QAAA,CAClB,OAAA,CAASF,EACT,SAAA,CAAWd,CACb,CAAC,CACH","file":"index.cjs","sourcesContent":["export const EFFECT_STYLES = `\n.pe-gradient-border {\n position: relative;\n isolation: isolate;\n border-radius: var(--pe-gb-radius, inherit);\n border-color: transparent;\n}\n\n.pe-gradient-border::before {\n content: '';\n position: absolute;\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n box-sizing: border-box;\n padding: var(--pe-gb-thickness, 2px);\n background: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9));\n pointer-events: none;\n\n /* Hollow out the center so only the ring remains. */\n -webkit-mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n mask-composite: exclude;\n}\n\n@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {\n .pe-gradient-border::before {\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n padding: 0;\n border: var(--pe-gb-thickness, 2px) solid;\n border-image: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9)) 1;\n }\n}\n\n.pe-glow {\n box-shadow:\n 0 0 var(--pe-glow-blur, 24px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.4) * 100%), transparent),\n 0 0 var(--pe-glow-spread, 2px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.2) * 100%), transparent);\n}\n\n.pe-noise {\n position: relative;\n}\n\n.pe-noise::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' seed='13' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E\");\n background-size: var(--pe-noise-size, 80px) var(--pe-noise-size, 80px);\n background-repeat: repeat;\n image-rendering: pixelated;\n filter: contrast(190%) brightness(110%);\n opacity: var(--pe-noise-opacity, 0.28);\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pe-noise::after {\n opacity: calc(var(--pe-noise-opacity, 0.28) * 0.9);\n }\n}\n`;\n","import { applyCssVars, applyEffectClass, ensureGlobalStyle } from '@protohiro/effects-core';\nimport { useCallback, useEffect, useState } from 'react';\n\ntype UseCssEffectInput = {\n className: string;\n userClassName?: string;\n vars: Record<string, string | undefined>;\n disabled?: boolean;\n styleId: string;\n styleText: string;\n};\n\nexport function useCssEffect<T extends HTMLElement>(input: UseCssEffectInput) {\n const [node, setNode] = useState<T | null>(null);\n\n useEffect(() => {\n if (!node || input.disabled) {\n return;\n }\n\n ensureGlobalStyle(input.styleId, input.styleText);\n\n const cleanups: Array<() => void> = [];\n cleanups.push(applyEffectClass(node, input.className));\n\n if (input.userClassName) {\n cleanups.push(applyEffectClass(node, input.userClassName));\n }\n\n cleanups.push(applyCssVars(node, input.vars));\n\n return () => {\n for (const cleanup of cleanups.reverse()) {\n cleanup();\n }\n };\n }, [\n node,\n input.className,\n input.userClassName,\n input.disabled,\n input.styleId,\n input.styleText,\n input.vars,\n ]);\n\n return useCallback((next: T | null) => {\n setNode(next);\n }, []);\n}\n","import { toCssAngle, toCssLength } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GradientBorderOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGradientBorderEffect<T extends HTMLElement = HTMLElement>(\n options: GradientBorderOptions = {},\n) {\n const vars = useMemo(\n () => ({\n '--pe-gb-thickness': toCssLength(options.thickness),\n '--pe-gb-radius': toCssLength(options.radius),\n '--pe-gb-colors': options.colors,\n '--pe-gb-angle': toCssAngle(options.angle),\n }),\n [options.thickness, options.radius, options.colors, options.angle],\n );\n\n return useCssEffect<T>({\n className: 'pe-gradient-border',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GlowOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGlowEffect<T extends HTMLElement = HTMLElement>(options: GlowOptions = {}) {\n const vars = useMemo(\n () => ({\n '--pe-glow-color': options.color,\n '--pe-glow-blur': toCssLength(options.blur),\n '--pe-glow-spread': toCssLength(options.spread),\n '--pe-glow-opacity': toCssNumber(options.opacity),\n }),\n [options.color, options.blur, options.spread, options.opacity],\n );\n\n return useCssEffect<T>({\n className: 'pe-glow',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { NoiseOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nfunction clampUnit(value: number | undefined): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (Number.isNaN(value)) {\n return undefined;\n }\n\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useNoiseEffect<T extends HTMLElement = HTMLElement>(options: NoiseOptions = {}) {\n const intensity = clampUnit(options.intensity);\n\n const vars = useMemo(\n () => ({\n '--pe-noise-size': toCssLength(options.size ?? 120),\n '--pe-noise-opacity': toCssNumber(intensity ?? 0.2),\n }),\n [options.size, intensity],\n );\n\n return useCssEffect<T>({\n className: 'pe-noise',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/effectStyles.ts","../src/shared/useCssEffect.ts","../src/effects/useGradientBorderEffect.ts","../src/effects/useGlowEffect.ts","../src/effects/useNoiseEffect.ts","../src/effects/useSpotlightEffect.ts"],"names":["EFFECT_STYLES","useCssEffect","input","node","setNode","useState","useEffect","ensureGlobalStyle","cleanups","applyEffectClass","applyCssVars","cleanup","useCallback","next","STYLE_ID","useGradientBorderEffect","options","vars","useMemo","toCssLength","toCssAngle","useGlowEffect","toCssNumber","clampUnit","value","useNoiseEffect","intensity","toCssPosition","toCssImage","trimmed","normalizeSpotlightSize","useSpotlightEffect","isRevealMode","size","softness","coreIntensity","revealOpacity","x","y","revealImage","onPointerMove","event"],"mappings":"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","file":"index.cjs","sourcesContent":["export const EFFECT_STYLES = `\n.pe-gradient-border {\n position: relative;\n isolation: isolate;\n border-radius: var(--pe-gb-radius, inherit);\n border-color: transparent;\n}\n\n.pe-gradient-border::before {\n content: '';\n position: absolute;\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n box-sizing: border-box;\n padding: var(--pe-gb-thickness, 2px);\n background: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9));\n pointer-events: none;\n\n /* Hollow out the center so only the ring remains. */\n -webkit-mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n mask-composite: exclude;\n}\n\n@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {\n .pe-gradient-border::before {\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n padding: 0;\n border: var(--pe-gb-thickness, 2px) solid;\n border-image: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9)) 1;\n }\n}\n\n.pe-glow {\n box-shadow:\n 0 0 var(--pe-glow-blur, 24px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.4) * 100%), transparent),\n 0 0 var(--pe-glow-spread, 2px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.2) * 100%), transparent);\n}\n\n.pe-noise {\n position: relative;\n}\n\n.pe-noise::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' seed='13' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E\");\n background-size: var(--pe-noise-size, 80px) var(--pe-noise-size, 80px);\n background-repeat: repeat;\n image-rendering: pixelated;\n filter: contrast(190%) brightness(110%);\n opacity: var(--pe-noise-opacity, 0.28);\n pointer-events: none;\n}\n\n.pe-spotlight {\n position: relative;\n isolation: isolate;\n}\n\n.pe-spotlight::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n opacity: var(--pe-spotlight-intensity, 0.45);\n background:\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n color-mix(\n in srgb,\n var(--pe-spotlight-color, #7dd3fc) calc(var(--pe-spotlight-core-intensity, 0.58) * 100%),\n white\n )\n 0%,\n color-mix(\n in srgb,\n var(--pe-spotlight-color, #7dd3fc) calc((0.48 + var(--pe-spotlight-core-intensity, 0.58) * 0.32) * 100%),\n white\n )\n calc(var(--pe-spotlight-size, 180px) * 0.14),\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 38%, transparent) calc(var(--pe-spotlight-size, 180px) * 0.4),\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 20%, transparent) var(--pe-spotlight-size, 180px),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.45)\n ),\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 16%, transparent) 0%,\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 8%, transparent) calc(var(--pe-spotlight-size, 180px) * 1.2),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.8)\n );\n mix-blend-mode: screen;\n filter: blur(calc(1px + var(--pe-spotlight-softness, 0.72) * 6px)) saturate(128%);\n transition: background 120ms ease-out, opacity 120ms ease-out;\n}\n\n@supports ((-webkit-mask-image: radial-gradient(white, black)) or (mask-image: radial-gradient(white, black))) {\n .pe-spotlight.pe-spotlight--reveal::before {\n opacity: var(--pe-spotlight-reveal-opacity, 0.92);\n background-image:\n var(\n --pe-spotlight-reveal-image,\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 220'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%236d28d9'/%3E%3Cstop offset='52%25' stop-color='%230ea5e9'/%3E%3Cstop offset='100%25' stop-color='%2322d3ee'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='320' height='220' fill='url(%23g)'/%3E%3Ccircle cx='86' cy='74' r='52' fill='rgba(255,255,255,0.24)'/%3E%3Ccircle cx='252' cy='154' r='70' fill='rgba(255,255,255,0.14)'/%3E%3C/svg%3E\")\n ),\n linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));\n background-size: var(--pe-spotlight-reveal-size, cover), cover;\n background-position: center;\n background-repeat: no-repeat;\n mix-blend-mode: normal;\n filter: saturate(120%);\n -webkit-mask-image: radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(0, 0, 0, 1) 0,\n rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),\n rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.22)\n );\n mask-image: radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(0, 0, 0, 1) 0,\n rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),\n rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.22)\n );\n }\n}\n\n@supports not (color: color-mix(in srgb, white, black)) {\n .pe-spotlight::before {\n background:\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(255, 255, 255, 0.86) 0%,\n rgba(255, 255, 255, 0.56) calc(var(--pe-spotlight-size, 180px) * 0.14),\n rgba(255, 255, 255, 0.3) calc(var(--pe-spotlight-size, 180px) * 0.4),\n rgba(255, 255, 255, 0.16) var(--pe-spotlight-size, 180px),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.45)\n ),\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(255, 255, 255, 0.16) 0%,\n rgba(255, 255, 255, 0.08) calc(var(--pe-spotlight-size, 180px) * 1.2),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.8)\n );\n }\n\n .pe-spotlight.pe-spotlight--reveal::before {\n background-image:\n var(--pe-spotlight-reveal-image, linear-gradient(135deg, rgba(109, 40, 217, 0.9), rgba(14, 165, 233, 0.95))),\n linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pe-noise::after {\n opacity: calc(var(--pe-noise-opacity, 0.28) * 0.9);\n }\n}\n`;\n","import { applyCssVars, applyEffectClass, ensureGlobalStyle } from '@protohiro/effects-core';\nimport { useCallback, useEffect, useState } from 'react';\n\ntype UseCssEffectInput = {\n className: string;\n userClassName?: string;\n vars: Record<string, string | undefined>;\n disabled?: boolean;\n styleId: string;\n styleText: string;\n};\n\nexport function useCssEffect<T extends HTMLElement>(input: UseCssEffectInput) {\n const [node, setNode] = useState<T | null>(null);\n\n useEffect(() => {\n if (!node || input.disabled) {\n return;\n }\n\n ensureGlobalStyle(input.styleId, input.styleText);\n\n const cleanups: Array<() => void> = [];\n cleanups.push(applyEffectClass(node, input.className));\n\n if (input.userClassName) {\n cleanups.push(applyEffectClass(node, input.userClassName));\n }\n\n cleanups.push(applyCssVars(node, input.vars));\n\n return () => {\n for (const cleanup of cleanups.reverse()) {\n cleanup();\n }\n };\n }, [\n node,\n input.className,\n input.userClassName,\n input.disabled,\n input.styleId,\n input.styleText,\n input.vars,\n ]);\n\n return useCallback((next: T | null) => {\n setNode(next);\n }, []);\n}\n","import { toCssAngle, toCssLength } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GradientBorderOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGradientBorderEffect<T extends HTMLElement = HTMLElement>(\n options: GradientBorderOptions = {},\n) {\n const vars = useMemo(\n () => ({\n '--pe-gb-thickness': toCssLength(options.thickness),\n '--pe-gb-radius': toCssLength(options.radius),\n '--pe-gb-colors': options.colors,\n '--pe-gb-angle': toCssAngle(options.angle),\n }),\n [options.thickness, options.radius, options.colors, options.angle],\n );\n\n return useCssEffect<T>({\n className: 'pe-gradient-border',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GlowOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGlowEffect<T extends HTMLElement = HTMLElement>(options: GlowOptions = {}) {\n const vars = useMemo(\n () => ({\n '--pe-glow-color': options.color,\n '--pe-glow-blur': toCssLength(options.blur),\n '--pe-glow-spread': toCssLength(options.spread),\n '--pe-glow-opacity': toCssNumber(options.opacity),\n }),\n [options.color, options.blur, options.spread, options.opacity],\n );\n\n return useCssEffect<T>({\n className: 'pe-glow',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { NoiseOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nfunction clampUnit(value: number | undefined): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (Number.isNaN(value)) {\n return undefined;\n }\n\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useNoiseEffect<T extends HTMLElement = HTMLElement>(options: NoiseOptions = {}) {\n const intensity = clampUnit(options.intensity);\n\n const vars = useMemo(\n () => ({\n '--pe-noise-size': toCssLength(options.size ?? 120),\n '--pe-noise-opacity': toCssNumber(intensity ?? 0.2),\n }),\n [options.size, intensity],\n );\n\n return useCssEffect<T>({\n className: 'pe-noise',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import {\n applyCssVars,\n applyEffectClass,\n ensureGlobalStyle,\n toCssLength,\n toCssNumber,\n} from '@protohiro/effects-core';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { SpotlightOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nfunction clampUnit(value: number | undefined): number | undefined {\n if (value === undefined || Number.isNaN(value)) {\n return undefined;\n }\n\n return Math.max(0, Math.min(1, value));\n}\n\nfunction toCssPosition(value: string | number | undefined): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return typeof value === 'number' ? `${value}%` : value;\n}\n\nfunction toCssImage(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (!trimmed) {\n return undefined;\n }\n\n if (\n trimmed.startsWith('url(') ||\n trimmed.startsWith('linear-gradient(') ||\n trimmed.startsWith('radial-gradient(') ||\n trimmed.startsWith('conic-gradient(')\n ) {\n return trimmed;\n }\n\n return `url(\"${trimmed.replace(/\"/g, '\\\\\"')}\")`;\n}\n\nfunction normalizeSpotlightSize(\n value: string | number | undefined,\n): string | number | undefined {\n if (value === undefined || typeof value !== 'number') {\n return value;\n }\n\n return Math.max(0, value);\n}\n\nexport function useSpotlightEffect<T extends HTMLElement = HTMLElement>(\n options: SpotlightOptions = {},\n) {\n const [node, setNode] = useState<T | null>(null);\n const isRevealMode = options.mode === 'reveal';\n const size = normalizeSpotlightSize(options.size);\n const intensity = clampUnit(options.intensity);\n const softness = clampUnit(options.softness);\n const coreIntensity = clampUnit(options.coreIntensity);\n const revealOpacity = clampUnit(options.revealOpacity);\n const x = toCssPosition(options.x);\n const y = toCssPosition(options.y);\n const revealImage = toCssImage(options.revealImage);\n\n const vars = useMemo(\n () => ({\n '--pe-spotlight-size': toCssLength(size),\n '--pe-spotlight-intensity': toCssNumber(intensity),\n '--pe-spotlight-color': options.color,\n '--pe-spotlight-softness': toCssNumber(softness),\n '--pe-spotlight-core-intensity': toCssNumber(coreIntensity),\n '--pe-spotlight-x': x,\n '--pe-spotlight-y': y,\n '--pe-spotlight-reveal-color': options.revealColor,\n '--pe-spotlight-reveal-image': revealImage,\n '--pe-spotlight-reveal-size': toCssLength(options.revealSize),\n '--pe-spotlight-reveal-opacity': toCssNumber(revealOpacity),\n }),\n [\n size,\n intensity,\n softness,\n coreIntensity,\n options.color,\n x,\n y,\n options.revealColor,\n revealImage,\n options.revealSize,\n revealOpacity,\n ],\n );\n\n useEffect(() => {\n if (!node || options.disabled) {\n return;\n }\n\n ensureGlobalStyle(STYLE_ID, EFFECT_STYLES);\n\n const cleanups: Array<() => void> = [];\n cleanups.push(applyEffectClass(node, 'pe-spotlight'));\n if (isRevealMode) {\n cleanups.push(applyEffectClass(node, 'pe-spotlight--reveal'));\n }\n\n if (options.className) {\n cleanups.push(applyEffectClass(node, options.className));\n }\n\n cleanups.push(applyCssVars(node, vars));\n\n return () => {\n for (const cleanup of cleanups.reverse()) {\n cleanup();\n }\n };\n }, [node, options.disabled, options.className, isRevealMode, vars]);\n\n useEffect(() => {\n if (!node || options.disabled || !options.followPointer) {\n return;\n }\n\n const onPointerMove = (event: PointerEvent) => {\n node.style.setProperty('--pe-spotlight-x', `${event.offsetX}px`);\n node.style.setProperty('--pe-spotlight-y', `${event.offsetY}px`);\n };\n\n node.addEventListener('pointermove', onPointerMove);\n\n return () => {\n node.removeEventListener('pointermove', onPointerMove);\n };\n }, [node, options.disabled, options.followPointer]);\n\n return useCallback((next: T | null) => {\n setNode(next);\n }, []);\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -18,6 +18,21 @@ interface NoiseOptions extends EffectBaseOptions {
|
|
|
18
18
|
size?: string | number;
|
|
19
19
|
intensity?: number;
|
|
20
20
|
}
|
|
21
|
+
interface SpotlightOptions extends EffectBaseOptions {
|
|
22
|
+
mode?: 'glow' | 'reveal';
|
|
23
|
+
size?: string | number;
|
|
24
|
+
intensity?: number;
|
|
25
|
+
color?: string;
|
|
26
|
+
softness?: number;
|
|
27
|
+
coreIntensity?: number;
|
|
28
|
+
x?: string | number;
|
|
29
|
+
y?: string | number;
|
|
30
|
+
followPointer?: boolean;
|
|
31
|
+
revealColor?: string;
|
|
32
|
+
revealImage?: string;
|
|
33
|
+
revealSize?: string | number;
|
|
34
|
+
revealOpacity?: number;
|
|
35
|
+
}
|
|
21
36
|
|
|
22
37
|
declare function useGradientBorderEffect<T extends HTMLElement = HTMLElement>(options?: GradientBorderOptions): (next: T | null) => void;
|
|
23
38
|
|
|
@@ -25,4 +40,6 @@ declare function useGlowEffect<T extends HTMLElement = HTMLElement>(options?: Gl
|
|
|
25
40
|
|
|
26
41
|
declare function useNoiseEffect<T extends HTMLElement = HTMLElement>(options?: NoiseOptions): (next: T | null) => void;
|
|
27
42
|
|
|
28
|
-
|
|
43
|
+
declare function useSpotlightEffect<T extends HTMLElement = HTMLElement>(options?: SpotlightOptions): (next: T | null) => void;
|
|
44
|
+
|
|
45
|
+
export { type EffectBaseOptions, type GlowOptions, type GradientBorderOptions, type NoiseOptions, type SpotlightOptions, useGlowEffect, useGradientBorderEffect, useNoiseEffect, useSpotlightEffect };
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,21 @@ interface NoiseOptions extends EffectBaseOptions {
|
|
|
18
18
|
size?: string | number;
|
|
19
19
|
intensity?: number;
|
|
20
20
|
}
|
|
21
|
+
interface SpotlightOptions extends EffectBaseOptions {
|
|
22
|
+
mode?: 'glow' | 'reveal';
|
|
23
|
+
size?: string | number;
|
|
24
|
+
intensity?: number;
|
|
25
|
+
color?: string;
|
|
26
|
+
softness?: number;
|
|
27
|
+
coreIntensity?: number;
|
|
28
|
+
x?: string | number;
|
|
29
|
+
y?: string | number;
|
|
30
|
+
followPointer?: boolean;
|
|
31
|
+
revealColor?: string;
|
|
32
|
+
revealImage?: string;
|
|
33
|
+
revealSize?: string | number;
|
|
34
|
+
revealOpacity?: number;
|
|
35
|
+
}
|
|
21
36
|
|
|
22
37
|
declare function useGradientBorderEffect<T extends HTMLElement = HTMLElement>(options?: GradientBorderOptions): (next: T | null) => void;
|
|
23
38
|
|
|
@@ -25,4 +40,6 @@ declare function useGlowEffect<T extends HTMLElement = HTMLElement>(options?: Gl
|
|
|
25
40
|
|
|
26
41
|
declare function useNoiseEffect<T extends HTMLElement = HTMLElement>(options?: NoiseOptions): (next: T | null) => void;
|
|
27
42
|
|
|
28
|
-
|
|
43
|
+
declare function useSpotlightEffect<T extends HTMLElement = HTMLElement>(options?: SpotlightOptions): (next: T | null) => void;
|
|
44
|
+
|
|
45
|
+
export { type EffectBaseOptions, type GlowOptions, type GradientBorderOptions, type NoiseOptions, type SpotlightOptions, useGlowEffect, useGradientBorderEffect, useNoiseEffect, useSpotlightEffect };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {toCssAngle,toCssLength,toCssNumber,ensureGlobalStyle,applyEffectClass,applyCssVars}from'@protohiro/effects-core';import {useMemo,useState,useEffect,useCallback}from'react';var
|
|
1
|
+
import {toCssAngle,toCssLength,toCssNumber,ensureGlobalStyle,applyEffectClass,applyCssVars}from'@protohiro/effects-core';import {useMemo,useState,useEffect,useCallback}from'react';var a=`
|
|
2
2
|
.pe-gradient-border {
|
|
3
3
|
position: relative;
|
|
4
4
|
isolation: isolate;
|
|
@@ -65,10 +65,109 @@ import {toCssAngle,toCssLength,toCssNumber,ensureGlobalStyle,applyEffectClass,ap
|
|
|
65
65
|
pointer-events: none;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
.pe-spotlight {
|
|
69
|
+
position: relative;
|
|
70
|
+
isolation: isolate;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.pe-spotlight::before {
|
|
74
|
+
content: '';
|
|
75
|
+
position: absolute;
|
|
76
|
+
inset: 0;
|
|
77
|
+
border-radius: inherit;
|
|
78
|
+
pointer-events: none;
|
|
79
|
+
opacity: var(--pe-spotlight-intensity, 0.45);
|
|
80
|
+
background:
|
|
81
|
+
radial-gradient(
|
|
82
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
83
|
+
color-mix(
|
|
84
|
+
in srgb,
|
|
85
|
+
var(--pe-spotlight-color, #7dd3fc) calc(var(--pe-spotlight-core-intensity, 0.58) * 100%),
|
|
86
|
+
white
|
|
87
|
+
)
|
|
88
|
+
0%,
|
|
89
|
+
color-mix(
|
|
90
|
+
in srgb,
|
|
91
|
+
var(--pe-spotlight-color, #7dd3fc) calc((0.48 + var(--pe-spotlight-core-intensity, 0.58) * 0.32) * 100%),
|
|
92
|
+
white
|
|
93
|
+
)
|
|
94
|
+
calc(var(--pe-spotlight-size, 180px) * 0.14),
|
|
95
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 38%, transparent) calc(var(--pe-spotlight-size, 180px) * 0.4),
|
|
96
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 20%, transparent) var(--pe-spotlight-size, 180px),
|
|
97
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.45)
|
|
98
|
+
),
|
|
99
|
+
radial-gradient(
|
|
100
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
101
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 16%, transparent) 0%,
|
|
102
|
+
color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 8%, transparent) calc(var(--pe-spotlight-size, 180px) * 1.2),
|
|
103
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.8)
|
|
104
|
+
);
|
|
105
|
+
mix-blend-mode: screen;
|
|
106
|
+
filter: blur(calc(1px + var(--pe-spotlight-softness, 0.72) * 6px)) saturate(128%);
|
|
107
|
+
transition: background 120ms ease-out, opacity 120ms ease-out;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@supports ((-webkit-mask-image: radial-gradient(white, black)) or (mask-image: radial-gradient(white, black))) {
|
|
111
|
+
.pe-spotlight.pe-spotlight--reveal::before {
|
|
112
|
+
opacity: var(--pe-spotlight-reveal-opacity, 0.92);
|
|
113
|
+
background-image:
|
|
114
|
+
var(
|
|
115
|
+
--pe-spotlight-reveal-image,
|
|
116
|
+
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 220'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%236d28d9'/%3E%3Cstop offset='52%25' stop-color='%230ea5e9'/%3E%3Cstop offset='100%25' stop-color='%2322d3ee'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='320' height='220' fill='url(%23g)'/%3E%3Ccircle cx='86' cy='74' r='52' fill='rgba(255,255,255,0.24)'/%3E%3Ccircle cx='252' cy='154' r='70' fill='rgba(255,255,255,0.14)'/%3E%3C/svg%3E")
|
|
117
|
+
),
|
|
118
|
+
linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));
|
|
119
|
+
background-size: var(--pe-spotlight-reveal-size, cover), cover;
|
|
120
|
+
background-position: center;
|
|
121
|
+
background-repeat: no-repeat;
|
|
122
|
+
mix-blend-mode: normal;
|
|
123
|
+
filter: saturate(120%);
|
|
124
|
+
-webkit-mask-image: radial-gradient(
|
|
125
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
126
|
+
rgba(0, 0, 0, 1) 0,
|
|
127
|
+
rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),
|
|
128
|
+
rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),
|
|
129
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.22)
|
|
130
|
+
);
|
|
131
|
+
mask-image: radial-gradient(
|
|
132
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
133
|
+
rgba(0, 0, 0, 1) 0,
|
|
134
|
+
rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),
|
|
135
|
+
rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),
|
|
136
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.22)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@supports not (color: color-mix(in srgb, white, black)) {
|
|
142
|
+
.pe-spotlight::before {
|
|
143
|
+
background:
|
|
144
|
+
radial-gradient(
|
|
145
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
146
|
+
rgba(255, 255, 255, 0.86) 0%,
|
|
147
|
+
rgba(255, 255, 255, 0.56) calc(var(--pe-spotlight-size, 180px) * 0.14),
|
|
148
|
+
rgba(255, 255, 255, 0.3) calc(var(--pe-spotlight-size, 180px) * 0.4),
|
|
149
|
+
rgba(255, 255, 255, 0.16) var(--pe-spotlight-size, 180px),
|
|
150
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.45)
|
|
151
|
+
),
|
|
152
|
+
radial-gradient(
|
|
153
|
+
circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),
|
|
154
|
+
rgba(255, 255, 255, 0.16) 0%,
|
|
155
|
+
rgba(255, 255, 255, 0.08) calc(var(--pe-spotlight-size, 180px) * 1.2),
|
|
156
|
+
transparent calc(var(--pe-spotlight-size, 180px) * 1.8)
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.pe-spotlight.pe-spotlight--reveal::before {
|
|
161
|
+
background-image:
|
|
162
|
+
var(--pe-spotlight-reveal-image, linear-gradient(135deg, rgba(109, 40, 217, 0.9), rgba(14, 165, 233, 0.95))),
|
|
163
|
+
linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
68
167
|
@media (prefers-reduced-motion: reduce) {
|
|
69
168
|
.pe-noise::after {
|
|
70
169
|
opacity: calc(var(--pe-noise-opacity, 0.28) * 0.9);
|
|
71
170
|
}
|
|
72
171
|
}
|
|
73
|
-
`;function
|
|
172
|
+
`;function i(e){let[t,o]=useState(null);return useEffect(()=>{if(!t||e.disabled)return;ensureGlobalStyle(e.styleId,e.styleText);let s=[];return s.push(applyEffectClass(t,e.className)),e.userClassName&&s.push(applyEffectClass(t,e.userClassName)),s.push(applyCssVars(t,e.vars)),()=>{for(let l of s.reverse())l();}},[t,e.className,e.userClassName,e.disabled,e.styleId,e.styleText,e.vars]),useCallback(s=>{o(s);},[])}var G="protohiro-effects-base";function F(e={}){let t=useMemo(()=>({"--pe-gb-thickness":toCssLength(e.thickness),"--pe-gb-radius":toCssLength(e.radius),"--pe-gb-colors":e.colors,"--pe-gb-angle":toCssAngle(e.angle)}),[e.thickness,e.radius,e.colors,e.angle]);return i({className:"pe-gradient-border",userClassName:e.className,vars:t,disabled:e.disabled,styleId:G,styleText:a})}var _="protohiro-effects-base";function B(e={}){let t=useMemo(()=>({"--pe-glow-color":e.color,"--pe-glow-blur":toCssLength(e.blur),"--pe-glow-spread":toCssLength(e.spread),"--pe-glow-opacity":toCssNumber(e.opacity)}),[e.color,e.blur,e.spread,e.opacity]);return i({className:"pe-glow",userClassName:e.className,vars:t,disabled:e.disabled,styleId:_,styleText:a})}var W="protohiro-effects-base";function $(e){if(e!==void 0&&!Number.isNaN(e))return Math.max(0,Math.min(1,e))}function A(e={}){let t=$(e.intensity),o=useMemo(()=>({"--pe-noise-size":toCssLength(e.size??120),"--pe-noise-opacity":toCssNumber(t??.2)}),[e.size,t]);return i({className:"pe-noise",userClassName:e.className,vars:o,disabled:e.disabled,styleId:W,styleText:a})}var J="protohiro-effects-base";function c(e){if(!(e===void 0||Number.isNaN(e)))return Math.max(0,Math.min(1,e))}function k(e){if(e!==void 0)return typeof e=="number"?`${e}%`:e}function K(e){if(!e)return;let t=e.trim();if(t)return t.startsWith("url(")||t.startsWith("linear-gradient(")||t.startsWith("radial-gradient(")||t.startsWith("conic-gradient(")?t:`url("${t.replace(/"/g,'\\"')}")`}function Q(e){return e===void 0||typeof e!="number"?e:Math.max(0,e)}function Z(e={}){let[t,o]=useState(null),s=e.mode==="reveal",l=Q(e.size),g=c(e.intensity),f=c(e.softness),m=c(e.coreIntensity),u=c(e.revealOpacity),b=k(e.x),h=k(e.y),v=K(e.revealImage),x=useMemo(()=>({"--pe-spotlight-size":toCssLength(l),"--pe-spotlight-intensity":toCssNumber(g),"--pe-spotlight-color":e.color,"--pe-spotlight-softness":toCssNumber(f),"--pe-spotlight-core-intensity":toCssNumber(m),"--pe-spotlight-x":b,"--pe-spotlight-y":h,"--pe-spotlight-reveal-color":e.revealColor,"--pe-spotlight-reveal-image":v,"--pe-spotlight-reveal-size":toCssLength(e.revealSize),"--pe-spotlight-reveal-opacity":toCssNumber(u)}),[l,g,f,m,e.color,b,h,e.revealColor,v,e.revealSize,u]);return useEffect(()=>{if(!t||e.disabled)return;ensureGlobalStyle(J,a);let r=[];return r.push(applyEffectClass(t,"pe-spotlight")),s&&r.push(applyEffectClass(t,"pe-spotlight--reveal")),e.className&&r.push(applyEffectClass(t,e.className)),r.push(applyCssVars(t,x)),()=>{for(let n of r.reverse())n();}},[t,e.disabled,e.className,s,x]),useEffect(()=>{if(!t||e.disabled||!e.followPointer)return;let r=n=>{t.style.setProperty("--pe-spotlight-x",`${n.offsetX}px`),t.style.setProperty("--pe-spotlight-y",`${n.offsetY}px`);};return t.addEventListener("pointermove",r),()=>{t.removeEventListener("pointermove",r);}},[t,e.disabled,e.followPointer]),useCallback(r=>{o(r);},[])}export{B as useGlowEffect,F as useGradientBorderEffect,A as useNoiseEffect,Z as useSpotlightEffect};//# sourceMappingURL=index.js.map
|
|
74
173
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/effectStyles.ts","../src/shared/useCssEffect.ts","../src/effects/useGradientBorderEffect.ts","../src/effects/useGlowEffect.ts","../src/effects/useNoiseEffect.ts"],"names":["EFFECT_STYLES","useCssEffect","input","node","setNode","useState","useEffect","ensureGlobalStyle","cleanups","applyEffectClass","applyCssVars","cleanup","useCallback","next","STYLE_ID","useGradientBorderEffect","options","vars","useMemo","toCssLength","toCssAngle","useGlowEffect","toCssNumber","clampUnit","value","useNoiseEffect","intensity"],"mappings":"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","file":"index.js","sourcesContent":["export const EFFECT_STYLES = `\n.pe-gradient-border {\n position: relative;\n isolation: isolate;\n border-radius: var(--pe-gb-radius, inherit);\n border-color: transparent;\n}\n\n.pe-gradient-border::before {\n content: '';\n position: absolute;\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n box-sizing: border-box;\n padding: var(--pe-gb-thickness, 2px);\n background: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9));\n pointer-events: none;\n\n /* Hollow out the center so only the ring remains. */\n -webkit-mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n mask-composite: exclude;\n}\n\n@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {\n .pe-gradient-border::before {\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n padding: 0;\n border: var(--pe-gb-thickness, 2px) solid;\n border-image: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9)) 1;\n }\n}\n\n.pe-glow {\n box-shadow:\n 0 0 var(--pe-glow-blur, 24px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.4) * 100%), transparent),\n 0 0 var(--pe-glow-spread, 2px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.2) * 100%), transparent);\n}\n\n.pe-noise {\n position: relative;\n}\n\n.pe-noise::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' seed='13' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E\");\n background-size: var(--pe-noise-size, 80px) var(--pe-noise-size, 80px);\n background-repeat: repeat;\n image-rendering: pixelated;\n filter: contrast(190%) brightness(110%);\n opacity: var(--pe-noise-opacity, 0.28);\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pe-noise::after {\n opacity: calc(var(--pe-noise-opacity, 0.28) * 0.9);\n }\n}\n`;\n","import { applyCssVars, applyEffectClass, ensureGlobalStyle } from '@protohiro/effects-core';\nimport { useCallback, useEffect, useState } from 'react';\n\ntype UseCssEffectInput = {\n className: string;\n userClassName?: string;\n vars: Record<string, string | undefined>;\n disabled?: boolean;\n styleId: string;\n styleText: string;\n};\n\nexport function useCssEffect<T extends HTMLElement>(input: UseCssEffectInput) {\n const [node, setNode] = useState<T | null>(null);\n\n useEffect(() => {\n if (!node || input.disabled) {\n return;\n }\n\n ensureGlobalStyle(input.styleId, input.styleText);\n\n const cleanups: Array<() => void> = [];\n cleanups.push(applyEffectClass(node, input.className));\n\n if (input.userClassName) {\n cleanups.push(applyEffectClass(node, input.userClassName));\n }\n\n cleanups.push(applyCssVars(node, input.vars));\n\n return () => {\n for (const cleanup of cleanups.reverse()) {\n cleanup();\n }\n };\n }, [\n node,\n input.className,\n input.userClassName,\n input.disabled,\n input.styleId,\n input.styleText,\n input.vars,\n ]);\n\n return useCallback((next: T | null) => {\n setNode(next);\n }, []);\n}\n","import { toCssAngle, toCssLength } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GradientBorderOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGradientBorderEffect<T extends HTMLElement = HTMLElement>(\n options: GradientBorderOptions = {},\n) {\n const vars = useMemo(\n () => ({\n '--pe-gb-thickness': toCssLength(options.thickness),\n '--pe-gb-radius': toCssLength(options.radius),\n '--pe-gb-colors': options.colors,\n '--pe-gb-angle': toCssAngle(options.angle),\n }),\n [options.thickness, options.radius, options.colors, options.angle],\n );\n\n return useCssEffect<T>({\n className: 'pe-gradient-border',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GlowOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGlowEffect<T extends HTMLElement = HTMLElement>(options: GlowOptions = {}) {\n const vars = useMemo(\n () => ({\n '--pe-glow-color': options.color,\n '--pe-glow-blur': toCssLength(options.blur),\n '--pe-glow-spread': toCssLength(options.spread),\n '--pe-glow-opacity': toCssNumber(options.opacity),\n }),\n [options.color, options.blur, options.spread, options.opacity],\n );\n\n return useCssEffect<T>({\n className: 'pe-glow',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { NoiseOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nfunction clampUnit(value: number | undefined): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (Number.isNaN(value)) {\n return undefined;\n }\n\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useNoiseEffect<T extends HTMLElement = HTMLElement>(options: NoiseOptions = {}) {\n const intensity = clampUnit(options.intensity);\n\n const vars = useMemo(\n () => ({\n '--pe-noise-size': toCssLength(options.size ?? 120),\n '--pe-noise-opacity': toCssNumber(intensity ?? 0.2),\n }),\n [options.size, intensity],\n );\n\n return useCssEffect<T>({\n className: 'pe-noise',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/effectStyles.ts","../src/shared/useCssEffect.ts","../src/effects/useGradientBorderEffect.ts","../src/effects/useGlowEffect.ts","../src/effects/useNoiseEffect.ts","../src/effects/useSpotlightEffect.ts"],"names":["EFFECT_STYLES","useCssEffect","input","node","setNode","useState","useEffect","ensureGlobalStyle","cleanups","applyEffectClass","applyCssVars","cleanup","useCallback","next","STYLE_ID","useGradientBorderEffect","options","vars","useMemo","toCssLength","toCssAngle","useGlowEffect","toCssNumber","clampUnit","value","useNoiseEffect","intensity","toCssPosition","toCssImage","trimmed","normalizeSpotlightSize","useSpotlightEffect","isRevealMode","size","softness","coreIntensity","revealOpacity","x","y","revealImage","onPointerMove","event"],"mappings":"oLAAO,IAAMA,CAAAA,CAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;ACA7B,CAAA,CAYO,SAASC,CAAAA,CAAoCC,EAA0B,CAC5E,GAAM,CAACC,CAAAA,CAAMC,CAAO,CAAA,CAAIC,QAAAA,CAAmB,IAAI,CAAA,CAE/C,OAAAC,UAAU,IAAM,CACd,GAAI,CAACH,CAAAA,EAAQD,EAAM,QAAA,CACjB,OAGFK,kBAAkBL,CAAAA,CAAM,OAAA,CAASA,EAAM,SAAS,CAAA,CAEhD,IAAMM,CAAAA,CAA8B,EAAC,CACrC,OAAAA,EAAS,IAAA,CAAKC,gBAAAA,CAAiBN,EAAMD,CAAAA,CAAM,SAAS,CAAC,CAAA,CAEjDA,EAAM,aAAA,EACRM,CAAAA,CAAS,KAAKC,gBAAAA,CAAiBN,CAAAA,CAAMD,EAAM,aAAa,CAAC,CAAA,CAG3DM,CAAAA,CAAS,KAAKE,YAAAA,CAAaP,CAAAA,CAAMD,EAAM,IAAI,CAAC,EAErC,IAAM,CACX,QAAWS,CAAAA,IAAWH,CAAAA,CAAS,SAAQ,CACrCG,CAAAA,GAEJ,CACF,CAAA,CAAG,CACDR,CAAAA,CACAD,CAAAA,CAAM,SAAA,CACNA,CAAAA,CAAM,cACNA,CAAAA,CAAM,QAAA,CACNA,EAAM,OAAA,CACNA,CAAAA,CAAM,UACNA,CAAAA,CAAM,IACR,CAAC,CAAA,CAEMU,YAAaC,CAAAA,EAAmB,CACrCT,EAAQS,CAAI,EACd,EAAG,EAAE,CACP,CC1CA,IAAMC,CAAAA,CAAW,wBAAA,CAEV,SAASC,CAAAA,CACdC,CAAAA,CAAiC,EAAC,CAClC,CACA,IAAMC,CAAAA,CAAOC,OAAAA,CACX,KAAO,CACL,mBAAA,CAAqBC,YAAYH,CAAAA,CAAQ,SAAS,EAClD,gBAAA,CAAkBG,WAAAA,CAAYH,CAAAA,CAAQ,MAAM,EAC5C,gBAAA,CAAkBA,CAAAA,CAAQ,OAC1B,eAAA,CAAiBI,UAAAA,CAAWJ,EAAQ,KAAK,CAC3C,CAAA,CAAA,CACA,CAACA,EAAQ,SAAA,CAAWA,CAAAA,CAAQ,OAAQA,CAAAA,CAAQ,MAAA,CAAQA,EAAQ,KAAK,CACnE,CAAA,CAEA,OAAOf,EAAgB,CACrB,SAAA,CAAW,qBACX,aAAA,CAAee,CAAAA,CAAQ,UACvB,IAAA,CAAAC,CAAAA,CACA,SAAUD,CAAAA,CAAQ,QAAA,CAClB,QAASF,CAAAA,CACT,SAAA,CAAWd,CACb,CAAC,CACH,CCvBA,IAAMc,CAAAA,CAAW,wBAAA,CAEV,SAASO,CAAAA,CAAmDL,EAAuB,EAAC,CAAG,CAC5F,IAAMC,CAAAA,CAAOC,QACX,KAAO,CACL,iBAAA,CAAmBF,CAAAA,CAAQ,MAC3B,gBAAA,CAAkBG,WAAAA,CAAYH,EAAQ,IAAI,CAAA,CAC1C,mBAAoBG,WAAAA,CAAYH,CAAAA,CAAQ,MAAM,CAAA,CAC9C,mBAAA,CAAqBM,YAAYN,CAAAA,CAAQ,OAAO,CAClD,CAAA,CAAA,CACA,CAACA,EAAQ,KAAA,CAAOA,CAAAA,CAAQ,IAAA,CAAMA,CAAAA,CAAQ,OAAQA,CAAAA,CAAQ,OAAO,CAC/D,CAAA,CAEA,OAAOf,EAAgB,CACrB,SAAA,CAAW,SAAA,CACX,aAAA,CAAee,EAAQ,SAAA,CACvB,IAAA,CAAAC,EACA,QAAA,CAAUD,CAAAA,CAAQ,SAClB,OAAA,CAASF,CAAAA,CACT,SAAA,CAAWd,CACb,CAAC,CACH,CCrBA,IAAMc,CAAAA,CAAW,yBAEjB,SAASS,CAAAA,CAAUC,EAA+C,CAChE,GAAIA,CAAAA,GAAU,MAAA,EAIV,QAAO,KAAA,CAAMA,CAAK,EAItB,OAAO,IAAA,CAAK,IAAI,CAAA,CAAG,IAAA,CAAK,GAAA,CAAI,CAAA,CAAGA,CAAK,CAAC,CACvC,CAEO,SAASC,CAAAA,CAAoDT,EAAwB,EAAC,CAAG,CAC9F,IAAMU,EAAYH,CAAAA,CAAUP,CAAAA,CAAQ,SAAS,CAAA,CAEvCC,CAAAA,CAAOC,QACX,KAAO,CACL,kBAAmBC,WAAAA,CAAYH,CAAAA,CAAQ,MAAQ,GAAG,CAAA,CAClD,qBAAsBM,WAAAA,CAAYI,CAAAA,EAAa,EAAG,CACpD,CAAA,CAAA,CACA,CAACV,CAAAA,CAAQ,KAAMU,CAAS,CAC1B,EAEA,OAAOzB,CAAAA,CAAgB,CACrB,SAAA,CAAW,UAAA,CACX,aAAA,CAAee,CAAAA,CAAQ,UACvB,IAAA,CAAAC,CAAAA,CACA,SAAUD,CAAAA,CAAQ,QAAA,CAClB,QAASF,CAAAA,CACT,SAAA,CAAWd,CACb,CAAC,CACH,CC5BA,IAAMc,CAAAA,CAAW,yBAEjB,SAASS,CAAAA,CAAUC,EAA+C,CAChE,GAAI,EAAAA,CAAAA,GAAU,QAAa,MAAA,CAAO,KAAA,CAAMA,CAAK,CAAA,CAAA,CAI7C,OAAO,KAAK,GAAA,CAAI,CAAA,CAAG,IAAA,CAAK,GAAA,CAAI,EAAGA,CAAK,CAAC,CACvC,CAEA,SAASG,EAAcH,CAAAA,CAAwD,CAC7E,GAAIA,CAAAA,GAAU,MAAA,CAId,OAAO,OAAOA,CAAAA,EAAU,SAAW,CAAA,EAAGA,CAAK,IAAMA,CACnD,CAEA,SAASI,CAAAA,CAAWJ,EAA+C,CACjE,GAAI,CAACA,CAAAA,CACH,OAGF,IAAMK,CAAAA,CAAUL,CAAAA,CAAM,IAAA,EAAK,CAC3B,GAAKK,CAAAA,CAIL,OACEA,EAAQ,UAAA,CAAW,MAAM,GACzBA,CAAAA,CAAQ,UAAA,CAAW,kBAAkB,CAAA,EACrCA,EAAQ,UAAA,CAAW,kBAAkB,GACrCA,CAAAA,CAAQ,UAAA,CAAW,iBAAiB,CAAA,CAE7BA,CAAAA,CAGF,QAAQA,CAAAA,CAAQ,OAAA,CAAQ,KAAM,KAAK,CAAC,IAC7C,CAEA,SAASC,EACPN,CAAAA,CAC6B,CAC7B,OAAIA,CAAAA,GAAU,QAAa,OAAOA,CAAAA,EAAU,SACnCA,CAAAA,CAGF,IAAA,CAAK,IAAI,CAAA,CAAGA,CAAK,CAC1B,CAEO,SAASO,CAAAA,CACdf,CAAAA,CAA4B,EAAC,CAC7B,CACA,GAAM,CAACb,CAAAA,CAAMC,CAAO,CAAA,CAAIC,SAAmB,IAAI,CAAA,CACzC2B,EAAehB,CAAAA,CAAQ,IAAA,GAAS,SAChCiB,CAAAA,CAAOH,CAAAA,CAAuBd,EAAQ,IAAI,CAAA,CAC1CU,EAAYH,CAAAA,CAAUP,CAAAA,CAAQ,SAAS,CAAA,CACvCkB,CAAAA,CAAWX,EAAUP,CAAAA,CAAQ,QAAQ,CAAA,CACrCmB,CAAAA,CAAgBZ,EAAUP,CAAAA,CAAQ,aAAa,EAC/CoB,CAAAA,CAAgBb,CAAAA,CAAUP,EAAQ,aAAa,CAAA,CAC/CqB,CAAAA,CAAIV,CAAAA,CAAcX,EAAQ,CAAC,CAAA,CAC3BsB,EAAIX,CAAAA,CAAcX,CAAAA,CAAQ,CAAC,CAAA,CAC3BuB,CAAAA,CAAcX,CAAAA,CAAWZ,CAAAA,CAAQ,WAAW,CAAA,CAE5CC,CAAAA,CAAOC,QACX,KAAO,CACL,sBAAuBC,WAAAA,CAAYc,CAAI,EACvC,0BAAA,CAA4BX,WAAAA,CAAYI,CAAS,CAAA,CACjD,sBAAA,CAAwBV,EAAQ,KAAA,CAChC,yBAAA,CAA2BM,YAAYY,CAAQ,CAAA,CAC/C,+BAAA,CAAiCZ,WAAAA,CAAYa,CAAa,CAAA,CAC1D,kBAAA,CAAoBE,EACpB,kBAAA,CAAoBC,CAAAA,CACpB,8BAA+BtB,CAAAA,CAAQ,WAAA,CACvC,6BAAA,CAA+BuB,CAAAA,CAC/B,6BAA8BpB,WAAAA,CAAYH,CAAAA,CAAQ,UAAU,CAAA,CAC5D,+BAAA,CAAiCM,YAAYc,CAAa,CAC5D,CAAA,CAAA,CACA,CACEH,EACAP,CAAAA,CACAQ,CAAAA,CACAC,EACAnB,CAAAA,CAAQ,KAAA,CACRqB,EACAC,CAAAA,CACAtB,CAAAA,CAAQ,YACRuB,CAAAA,CACAvB,CAAAA,CAAQ,WACRoB,CACF,CACF,EAEA,OAAA9B,SAAAA,CAAU,IAAM,CACd,GAAI,CAACH,CAAAA,EAAQa,EAAQ,QAAA,CACnB,OAGFT,kBAAkBO,CAAAA,CAAUd,CAAa,EAEzC,IAAMQ,CAAAA,CAA8B,EAAC,CACrC,OAAAA,CAAAA,CAAS,IAAA,CAAKC,iBAAiBN,CAAAA,CAAM,cAAc,CAAC,CAAA,CAChD6B,CAAAA,EACFxB,CAAAA,CAAS,IAAA,CAAKC,iBAAiBN,CAAAA,CAAM,sBAAsB,CAAC,CAAA,CAG1Da,CAAAA,CAAQ,WACVR,CAAAA,CAAS,IAAA,CAAKC,iBAAiBN,CAAAA,CAAMa,CAAAA,CAAQ,SAAS,CAAC,CAAA,CAGzDR,EAAS,IAAA,CAAKE,YAAAA,CAAaP,EAAMc,CAAI,CAAC,CAAA,CAE/B,IAAM,CACX,IAAA,IAAWN,CAAAA,IAAWH,EAAS,OAAA,EAAQ,CACrCG,IAEJ,CACF,CAAA,CAAG,CAACR,EAAMa,CAAAA,CAAQ,QAAA,CAAUA,EAAQ,SAAA,CAAWgB,CAAAA,CAAcf,CAAI,CAAC,CAAA,CAElEX,SAAAA,CAAU,IAAM,CACd,GAAI,CAACH,GAAQa,CAAAA,CAAQ,QAAA,EAAY,CAACA,CAAAA,CAAQ,aAAA,CACxC,OAGF,IAAMwB,CAAAA,CAAiBC,GAAwB,CAC7CtC,CAAAA,CAAK,MAAM,WAAA,CAAY,kBAAA,CAAoB,GAAGsC,CAAAA,CAAM,OAAO,CAAA,EAAA,CAAI,CAAA,CAC/DtC,EAAK,KAAA,CAAM,WAAA,CAAY,mBAAoB,CAAA,EAAGsC,CAAAA,CAAM,OAAO,CAAA,EAAA,CAAI,EACjE,EAEA,OAAAtC,CAAAA,CAAK,iBAAiB,aAAA,CAAeqC,CAAa,EAE3C,IAAM,CACXrC,EAAK,mBAAA,CAAoB,aAAA,CAAeqC,CAAa,EACvD,CACF,CAAA,CAAG,CAACrC,EAAMa,CAAAA,CAAQ,QAAA,CAAUA,EAAQ,aAAa,CAAC,EAE3CJ,WAAAA,CAAaC,CAAAA,EAAmB,CACrCT,CAAAA,CAAQS,CAAI,EACd,CAAA,CAAG,EAAE,CACP","file":"index.js","sourcesContent":["export const EFFECT_STYLES = `\n.pe-gradient-border {\n position: relative;\n isolation: isolate;\n border-radius: var(--pe-gb-radius, inherit);\n border-color: transparent;\n}\n\n.pe-gradient-border::before {\n content: '';\n position: absolute;\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n box-sizing: border-box;\n padding: var(--pe-gb-thickness, 2px);\n background: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9));\n pointer-events: none;\n\n /* Hollow out the center so only the ring remains. */\n -webkit-mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask:\n linear-gradient(#fff 0 0) content-box,\n linear-gradient(#fff 0 0);\n mask-composite: exclude;\n}\n\n@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {\n .pe-gradient-border::before {\n z-index: -1;\n inset: calc(var(--pe-gb-thickness, 2px) * -1);\n border-radius: calc(var(--pe-gb-radius, 0px) + var(--pe-gb-thickness, 2px));\n padding: 0;\n border: var(--pe-gb-thickness, 2px) solid;\n border-image: linear-gradient(var(--pe-gb-angle, 120deg), var(--pe-gb-colors, #5eead4, #0ea5e9)) 1;\n }\n}\n\n.pe-glow {\n box-shadow:\n 0 0 var(--pe-glow-blur, 24px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.4) * 100%), transparent),\n 0 0 var(--pe-glow-spread, 2px)\n color-mix(in srgb, var(--pe-glow-color, #38bdf8) calc(var(--pe-glow-opacity, 0.2) * 100%), transparent);\n}\n\n.pe-noise {\n position: relative;\n}\n\n.pe-noise::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' seed='13' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E\");\n background-size: var(--pe-noise-size, 80px) var(--pe-noise-size, 80px);\n background-repeat: repeat;\n image-rendering: pixelated;\n filter: contrast(190%) brightness(110%);\n opacity: var(--pe-noise-opacity, 0.28);\n pointer-events: none;\n}\n\n.pe-spotlight {\n position: relative;\n isolation: isolate;\n}\n\n.pe-spotlight::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n opacity: var(--pe-spotlight-intensity, 0.45);\n background:\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n color-mix(\n in srgb,\n var(--pe-spotlight-color, #7dd3fc) calc(var(--pe-spotlight-core-intensity, 0.58) * 100%),\n white\n )\n 0%,\n color-mix(\n in srgb,\n var(--pe-spotlight-color, #7dd3fc) calc((0.48 + var(--pe-spotlight-core-intensity, 0.58) * 0.32) * 100%),\n white\n )\n calc(var(--pe-spotlight-size, 180px) * 0.14),\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 38%, transparent) calc(var(--pe-spotlight-size, 180px) * 0.4),\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 20%, transparent) var(--pe-spotlight-size, 180px),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.45)\n ),\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 16%, transparent) 0%,\n color-mix(in srgb, var(--pe-spotlight-color, #7dd3fc) 8%, transparent) calc(var(--pe-spotlight-size, 180px) * 1.2),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.8)\n );\n mix-blend-mode: screen;\n filter: blur(calc(1px + var(--pe-spotlight-softness, 0.72) * 6px)) saturate(128%);\n transition: background 120ms ease-out, opacity 120ms ease-out;\n}\n\n@supports ((-webkit-mask-image: radial-gradient(white, black)) or (mask-image: radial-gradient(white, black))) {\n .pe-spotlight.pe-spotlight--reveal::before {\n opacity: var(--pe-spotlight-reveal-opacity, 0.92);\n background-image:\n var(\n --pe-spotlight-reveal-image,\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 220'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%236d28d9'/%3E%3Cstop offset='52%25' stop-color='%230ea5e9'/%3E%3Cstop offset='100%25' stop-color='%2322d3ee'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='320' height='220' fill='url(%23g)'/%3E%3Ccircle cx='86' cy='74' r='52' fill='rgba(255,255,255,0.24)'/%3E%3Ccircle cx='252' cy='154' r='70' fill='rgba(255,255,255,0.14)'/%3E%3C/svg%3E\")\n ),\n linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));\n background-size: var(--pe-spotlight-reveal-size, cover), cover;\n background-position: center;\n background-repeat: no-repeat;\n mix-blend-mode: normal;\n filter: saturate(120%);\n -webkit-mask-image: radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(0, 0, 0, 1) 0,\n rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),\n rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.22)\n );\n mask-image: radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(0, 0, 0, 1) 0,\n rgba(0, 0, 0, 1) calc(var(--pe-spotlight-size, 180px) * 0.36),\n rgba(0, 0, 0, 0.75) calc(var(--pe-spotlight-size, 180px) * 0.72),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.22)\n );\n }\n}\n\n@supports not (color: color-mix(in srgb, white, black)) {\n .pe-spotlight::before {\n background:\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(255, 255, 255, 0.86) 0%,\n rgba(255, 255, 255, 0.56) calc(var(--pe-spotlight-size, 180px) * 0.14),\n rgba(255, 255, 255, 0.3) calc(var(--pe-spotlight-size, 180px) * 0.4),\n rgba(255, 255, 255, 0.16) var(--pe-spotlight-size, 180px),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.45)\n ),\n radial-gradient(\n circle at var(--pe-spotlight-x, 50%) var(--pe-spotlight-y, 50%),\n rgba(255, 255, 255, 0.16) 0%,\n rgba(255, 255, 255, 0.08) calc(var(--pe-spotlight-size, 180px) * 1.2),\n transparent calc(var(--pe-spotlight-size, 180px) * 1.8)\n );\n }\n\n .pe-spotlight.pe-spotlight--reveal::before {\n background-image:\n var(--pe-spotlight-reveal-image, linear-gradient(135deg, rgba(109, 40, 217, 0.9), rgba(14, 165, 233, 0.95))),\n linear-gradient(var(--pe-spotlight-reveal-color, #38bdf8), var(--pe-spotlight-reveal-color, #38bdf8));\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pe-noise::after {\n opacity: calc(var(--pe-noise-opacity, 0.28) * 0.9);\n }\n}\n`;\n","import { applyCssVars, applyEffectClass, ensureGlobalStyle } from '@protohiro/effects-core';\nimport { useCallback, useEffect, useState } from 'react';\n\ntype UseCssEffectInput = {\n className: string;\n userClassName?: string;\n vars: Record<string, string | undefined>;\n disabled?: boolean;\n styleId: string;\n styleText: string;\n};\n\nexport function useCssEffect<T extends HTMLElement>(input: UseCssEffectInput) {\n const [node, setNode] = useState<T | null>(null);\n\n useEffect(() => {\n if (!node || input.disabled) {\n return;\n }\n\n ensureGlobalStyle(input.styleId, input.styleText);\n\n const cleanups: Array<() => void> = [];\n cleanups.push(applyEffectClass(node, input.className));\n\n if (input.userClassName) {\n cleanups.push(applyEffectClass(node, input.userClassName));\n }\n\n cleanups.push(applyCssVars(node, input.vars));\n\n return () => {\n for (const cleanup of cleanups.reverse()) {\n cleanup();\n }\n };\n }, [\n node,\n input.className,\n input.userClassName,\n input.disabled,\n input.styleId,\n input.styleText,\n input.vars,\n ]);\n\n return useCallback((next: T | null) => {\n setNode(next);\n }, []);\n}\n","import { toCssAngle, toCssLength } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GradientBorderOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGradientBorderEffect<T extends HTMLElement = HTMLElement>(\n options: GradientBorderOptions = {},\n) {\n const vars = useMemo(\n () => ({\n '--pe-gb-thickness': toCssLength(options.thickness),\n '--pe-gb-radius': toCssLength(options.radius),\n '--pe-gb-colors': options.colors,\n '--pe-gb-angle': toCssAngle(options.angle),\n }),\n [options.thickness, options.radius, options.colors, options.angle],\n );\n\n return useCssEffect<T>({\n className: 'pe-gradient-border',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { GlowOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nexport function useGlowEffect<T extends HTMLElement = HTMLElement>(options: GlowOptions = {}) {\n const vars = useMemo(\n () => ({\n '--pe-glow-color': options.color,\n '--pe-glow-blur': toCssLength(options.blur),\n '--pe-glow-spread': toCssLength(options.spread),\n '--pe-glow-opacity': toCssNumber(options.opacity),\n }),\n [options.color, options.blur, options.spread, options.opacity],\n );\n\n return useCssEffect<T>({\n className: 'pe-glow',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import { toCssLength, toCssNumber } from '@protohiro/effects-core';\nimport { useMemo } from 'react';\n\nimport type { NoiseOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\nimport { useCssEffect } from '../shared/useCssEffect';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nfunction clampUnit(value: number | undefined): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (Number.isNaN(value)) {\n return undefined;\n }\n\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useNoiseEffect<T extends HTMLElement = HTMLElement>(options: NoiseOptions = {}) {\n const intensity = clampUnit(options.intensity);\n\n const vars = useMemo(\n () => ({\n '--pe-noise-size': toCssLength(options.size ?? 120),\n '--pe-noise-opacity': toCssNumber(intensity ?? 0.2),\n }),\n [options.size, intensity],\n );\n\n return useCssEffect<T>({\n className: 'pe-noise',\n userClassName: options.className,\n vars,\n disabled: options.disabled,\n styleId: STYLE_ID,\n styleText: EFFECT_STYLES,\n });\n}\n","import {\n applyCssVars,\n applyEffectClass,\n ensureGlobalStyle,\n toCssLength,\n toCssNumber,\n} from '@protohiro/effects-core';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { SpotlightOptions } from '../types';\nimport { EFFECT_STYLES } from '../shared/effectStyles';\n\nconst STYLE_ID = 'protohiro-effects-base';\n\nfunction clampUnit(value: number | undefined): number | undefined {\n if (value === undefined || Number.isNaN(value)) {\n return undefined;\n }\n\n return Math.max(0, Math.min(1, value));\n}\n\nfunction toCssPosition(value: string | number | undefined): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return typeof value === 'number' ? `${value}%` : value;\n}\n\nfunction toCssImage(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (!trimmed) {\n return undefined;\n }\n\n if (\n trimmed.startsWith('url(') ||\n trimmed.startsWith('linear-gradient(') ||\n trimmed.startsWith('radial-gradient(') ||\n trimmed.startsWith('conic-gradient(')\n ) {\n return trimmed;\n }\n\n return `url(\"${trimmed.replace(/\"/g, '\\\\\"')}\")`;\n}\n\nfunction normalizeSpotlightSize(\n value: string | number | undefined,\n): string | number | undefined {\n if (value === undefined || typeof value !== 'number') {\n return value;\n }\n\n return Math.max(0, value);\n}\n\nexport function useSpotlightEffect<T extends HTMLElement = HTMLElement>(\n options: SpotlightOptions = {},\n) {\n const [node, setNode] = useState<T | null>(null);\n const isRevealMode = options.mode === 'reveal';\n const size = normalizeSpotlightSize(options.size);\n const intensity = clampUnit(options.intensity);\n const softness = clampUnit(options.softness);\n const coreIntensity = clampUnit(options.coreIntensity);\n const revealOpacity = clampUnit(options.revealOpacity);\n const x = toCssPosition(options.x);\n const y = toCssPosition(options.y);\n const revealImage = toCssImage(options.revealImage);\n\n const vars = useMemo(\n () => ({\n '--pe-spotlight-size': toCssLength(size),\n '--pe-spotlight-intensity': toCssNumber(intensity),\n '--pe-spotlight-color': options.color,\n '--pe-spotlight-softness': toCssNumber(softness),\n '--pe-spotlight-core-intensity': toCssNumber(coreIntensity),\n '--pe-spotlight-x': x,\n '--pe-spotlight-y': y,\n '--pe-spotlight-reveal-color': options.revealColor,\n '--pe-spotlight-reveal-image': revealImage,\n '--pe-spotlight-reveal-size': toCssLength(options.revealSize),\n '--pe-spotlight-reveal-opacity': toCssNumber(revealOpacity),\n }),\n [\n size,\n intensity,\n softness,\n coreIntensity,\n options.color,\n x,\n y,\n options.revealColor,\n revealImage,\n options.revealSize,\n revealOpacity,\n ],\n );\n\n useEffect(() => {\n if (!node || options.disabled) {\n return;\n }\n\n ensureGlobalStyle(STYLE_ID, EFFECT_STYLES);\n\n const cleanups: Array<() => void> = [];\n cleanups.push(applyEffectClass(node, 'pe-spotlight'));\n if (isRevealMode) {\n cleanups.push(applyEffectClass(node, 'pe-spotlight--reveal'));\n }\n\n if (options.className) {\n cleanups.push(applyEffectClass(node, options.className));\n }\n\n cleanups.push(applyCssVars(node, vars));\n\n return () => {\n for (const cleanup of cleanups.reverse()) {\n cleanup();\n }\n };\n }, [node, options.disabled, options.className, isRevealMode, vars]);\n\n useEffect(() => {\n if (!node || options.disabled || !options.followPointer) {\n return;\n }\n\n const onPointerMove = (event: PointerEvent) => {\n node.style.setProperty('--pe-spotlight-x', `${event.offsetX}px`);\n node.style.setProperty('--pe-spotlight-y', `${event.offsetY}px`);\n };\n\n node.addEventListener('pointermove', onPointerMove);\n\n return () => {\n node.removeEventListener('pointermove', onPointerMove);\n };\n }, [node, options.disabled, options.followPointer]);\n\n return useCallback((next: T | null) => {\n setNode(next);\n }, []);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protohiro/effects",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Zero-wrapper React hooks for composable CSS effects.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,10 +18,19 @@
|
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
20
20
|
"protoeffects",
|
|
21
|
+
"protohiro",
|
|
21
22
|
"react",
|
|
22
23
|
"hooks",
|
|
23
24
|
"css",
|
|
24
|
-
"effects"
|
|
25
|
+
"effects",
|
|
26
|
+
"react-hooks",
|
|
27
|
+
"css-effects",
|
|
28
|
+
"ui-effects",
|
|
29
|
+
"gradient-border",
|
|
30
|
+
"glow",
|
|
31
|
+
"spotlight",
|
|
32
|
+
"noise-overlay",
|
|
33
|
+
"design-system"
|
|
25
34
|
],
|
|
26
35
|
"publishConfig": {
|
|
27
36
|
"access": "public"
|
|
@@ -39,7 +48,7 @@
|
|
|
39
48
|
],
|
|
40
49
|
"sideEffects": false,
|
|
41
50
|
"dependencies": {
|
|
42
|
-
"@protohiro/effects-core": "0.1.
|
|
51
|
+
"@protohiro/effects-core": "0.1.3"
|
|
43
52
|
},
|
|
44
53
|
"peerDependencies": {
|
|
45
54
|
"react": "^18.0.0",
|