1+ <script setup>
2+ import { shiftHue , XMLNS } from " ../lib" ;
3+
4+ const props = defineProps ({
5+ config: { type: Object },
6+ unit: { type: Number },
7+ currentRating: { type: Number },
8+ getActiveColor: { type: Function },
9+ calcShapeFill: { type: Function },
10+ isReadonly: { type: Boolean },
11+ hasBreakdown: { type: Boolean },
12+ hoveredValue: { type: Number }
13+ });
14+
15+ const emit = defineEmits ([' rate' , ' mouseenter' , ' mouseleave' ,])
16+
17+ </script >
18+
19+ <template >
20+ <div
21+ :data-cy =" `smiley-item-${unit - 1}`"
22+ tabindex =" 0"
23+ :class =" { 'vue-ui-smiley-rated' : !config.readonly && currentRating === unit }"
24+ :style =" {
25+ cursor: config.readonly ? 'default' : 'pointer',
26+ height: config.style.itemSize + 'px',
27+ aspectRatio: '1/1',
28+ position: 'relative'
29+ }"
30+ @mouseenter =" emit('mouseenter')"
31+ @mouseleave =" emit('mouseleave')"
32+ @click =" emit('rate', unit)"
33+ @keyup.enter =" emit('rate', unit)"
34+ >
35+ <template v-if =" config .style .tooltip .show && hasBreakdown && isReadonly " >
36+ <div
37+ :data-cy =" `smiley-tooltip-${unit - 1}`"
38+ class =" vue-ui-rating-tooltip"
39+ :style =" {
40+ border: `1px solid ${config.style.tooltip.borderColor}`,
41+ position: 'absolute',
42+ top: `${config.style.tooltip.offsetY - 48}px`,
43+ left: '50%',
44+ transform: 'translateX(-50%)',
45+ width: 'fit-content',
46+ textAlign: 'center',
47+ background: config.style.tooltip.backgroundColor,
48+ display: hoveredValue === unit - 1 ? 'block' : 'none',
49+ padding: '2px 12px',
50+ borderRadius: config.style.tooltip.borderRadius + 'px',
51+ boxShadow: config.style.tooltip.boxShadow
52+ }"
53+ >
54+ <div :style =" {
55+ width: '100%',
56+ display: 'flex',
57+ flexDirection: 'row',
58+ gap: '6px',
59+ position: 'relative',
60+ textAlign: 'center',
61+ color: config.style.tooltip.color
62+ }"
63+ >
64+ <span :style =" `font-size:${config.style.tooltip.fontSize}px`" >{{ unit }}:</span >
65+ <span :style =" `font-weight:${config.style.tooltip.bold ? 'bold' : 'normal'};font-size:${config.style.tooltip.fontSize}px`" >
66+ <slot name =" rating" ></slot >
67+ </span >
68+
69+ <div :style =" `font-family:Arial !important;position:absolute;top:calc(100% - 4px);left:50%;transform:translateX(-50%);color:${config.style.tooltip.borderColor}`" >
70+ ▼
71+ </div >
72+ </div >
73+ </div >
74+ </template >
75+
76+ <svg :xmlns =" XMLNS" v-if =" config.style.icons.filled" style =" transition : all 0.1s ease-in-out ;position :absolute ;top :0 ;left :0 " height =" 100%" viewBox =" 0 0 24 24" stroke-width =" 1.5" :stroke =" getActiveColor(unit - 1)" fill =" none" stroke-linecap =" round" stroke-linejoin =" round" >
77+ <defs >
78+ <radialGradient :id =" `vueUiSmiley${unit - 1}`" >
79+ <stop offset =" 0%" :stop-color =" shiftHue(config.style.colors.active[unit - 1], 0.05)" />
80+ <stop offset =" 100%" :stop-color =" config.style.colors.active[unit - 1]" />
81+ </radialGradient >
82+ </defs >
83+ <slot name =" path-icon-filled" ></slot >
84+ </svg >
85+
86+ <svg v-else style =" position :absolute ;top :0 ;left :0 ;transition : all 0.1s ease-in-out ;" height =" 100%" viewBox =" 0 0 24 24" stroke-width =" 1.5" :stroke =" getActiveColor(unit - 1)" fill =" none" stroke-linecap =" round" stroke-linejoin =" round" >
87+ <slot name =" path-icon" ></slot >
88+ </svg >
89+
90+ <!-- RATING -->
91+ <svg :xmlns =" XMLNS" v-if =" config.style.icons.filled && isReadonly" style =" transition : all 0.1s ease-in-out ;position :absolute ;top :0 ;left :0 " height =" 100%" :viewBox =" `0 0 ${calcShapeFill(unit - 1)} 24`" stroke-width =" 1.5" :stroke =" config.style.colors.activeReadonly[unit - 1]" fill =" none" stroke-linecap =" round" stroke-linejoin =" round" >
92+ <defs >
93+ <radialGradient :id =" `vueUiSmiley${unit - 1}`" >
94+ <stop offset =" 0%" :stop-color =" shiftHue(config.style.colors.activeReadonly[unit - 1], 0.05)" />
95+ <stop offset =" 100%" :stop-color =" config.style.colors.activeReadonly[unit - 1]" />
96+ </radialGradient >
97+ </defs >
98+ <slot name =" path-icon-filled-readonly" ></slot >
99+ </svg >
100+
101+ <svg v-if =" !config.style.icons.filled && isReadonly" style =" position :absolute ;top :0 ;left :0 ;transition : all 0.1s ease-in-out ;" height =" 100%" :viewBox =" `0 0 ${calcShapeFill(unit - 1)} 24`" stroke-width =" 1.5" :stroke =" config.style.colors.activeReadonly[unit - 1]" fill =" none" stroke-linecap =" round" stroke-linejoin =" round" >
102+ <slot name =" path-icon-readonly" ></slot >
103+ </svg >
104+ </div >
105+ </template >
106+
107+ <style scoped>
108+ .vue-ui-smiley-rated {
109+ animation : vue-ui-smile 0.3s ease-in-out ;
110+ transform-origin : center ;
111+ }
112+
113+ @keyframes vue-ui-smile {
114+ 0% {
115+ transform : scale (0.9 , 0.9 );
116+ }
117+ 50% {
118+ transform : scale (1.2 ,1.2 );
119+ }
120+ 75% {
121+ transform : scale (0.95 , 0.95 );
122+ }
123+ 90% {
124+ transform : scale (1.1 ,1.1 );
125+ }
126+ 100% {
127+ transform : scale (1 , 1 );
128+ }
129+ }
130+ </style >
0 commit comments