@seekora-ai/ui-sdk-vanilla 0.2.11 → 0.2.13
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/dist/components/rating-display.d.ts +39 -0
- package/dist/components/rating-display.d.ts.map +1 -0
- package/dist/components/rating-display.js +192 -0
- package/dist/index.d.ts +41 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +194 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +195 -0
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,6 +2,199 @@
|
|
|
2
2
|
|
|
3
3
|
var uiSdkCore = require('@seekora-ai/ui-sdk-core');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* RatingDisplay - Vanilla JS
|
|
7
|
+
*
|
|
8
|
+
* Star rating display with review count and multiple variants
|
|
9
|
+
*/
|
|
10
|
+
const sizeMap = {
|
|
11
|
+
small: 14,
|
|
12
|
+
medium: 18,
|
|
13
|
+
large: 24,
|
|
14
|
+
};
|
|
15
|
+
const fontSizeMap = {
|
|
16
|
+
small: '0.75rem',
|
|
17
|
+
medium: '0.875rem',
|
|
18
|
+
large: '1rem',
|
|
19
|
+
};
|
|
20
|
+
class RatingDisplay {
|
|
21
|
+
constructor(containerOrSelector, options) {
|
|
22
|
+
this.hoverRating = null;
|
|
23
|
+
this.container = typeof containerOrSelector === 'string'
|
|
24
|
+
? document.querySelector(containerOrSelector)
|
|
25
|
+
: containerOrSelector;
|
|
26
|
+
if (!this.container) {
|
|
27
|
+
throw new Error('RatingDisplay: Container element not found');
|
|
28
|
+
}
|
|
29
|
+
this.options = {
|
|
30
|
+
variant: 'compact',
|
|
31
|
+
size: 'medium',
|
|
32
|
+
maxRating: 5,
|
|
33
|
+
showNumeric: false,
|
|
34
|
+
showHalfStars: true,
|
|
35
|
+
interactive: false,
|
|
36
|
+
starColor: '#f59e0b',
|
|
37
|
+
emptyStarColor: '#d1d5db',
|
|
38
|
+
textColor: 'var(--seekora-text-secondary, #6b7280)',
|
|
39
|
+
showReviewCount: true,
|
|
40
|
+
onRatingChange: () => { },
|
|
41
|
+
reviewCountFormat: this.defaultReviewCountFormat,
|
|
42
|
+
className: '',
|
|
43
|
+
...options,
|
|
44
|
+
};
|
|
45
|
+
this.render();
|
|
46
|
+
}
|
|
47
|
+
defaultReviewCountFormat(count) {
|
|
48
|
+
if (count >= 1000000)
|
|
49
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
50
|
+
if (count >= 1000)
|
|
51
|
+
return `${(count / 1000).toFixed(1)}K`;
|
|
52
|
+
return count.toString();
|
|
53
|
+
}
|
|
54
|
+
createStarSVG(filled, half, size) {
|
|
55
|
+
const { starColor, emptyStarColor } = this.options;
|
|
56
|
+
if (half) {
|
|
57
|
+
return `
|
|
58
|
+
<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
59
|
+
<defs>
|
|
60
|
+
<linearGradient id="half-fill-${Math.random()}">
|
|
61
|
+
<stop offset="50%" stop-color="${starColor}" />
|
|
62
|
+
<stop offset="50%" stop-color="${emptyStarColor}" />
|
|
63
|
+
</linearGradient>
|
|
64
|
+
</defs>
|
|
65
|
+
<path
|
|
66
|
+
d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"
|
|
67
|
+
fill="url(#half-fill-${Math.random()})"
|
|
68
|
+
stroke="${starColor}"
|
|
69
|
+
stroke-width="1"
|
|
70
|
+
/>
|
|
71
|
+
</svg>
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
return `
|
|
75
|
+
<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="${filled ? starColor : 'none'}" xmlns="http://www.w3.org/2000/svg">
|
|
76
|
+
<path
|
|
77
|
+
d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"
|
|
78
|
+
stroke="${filled ? starColor : emptyStarColor}"
|
|
79
|
+
stroke-width="1.5"
|
|
80
|
+
stroke-linecap="round"
|
|
81
|
+
stroke-linejoin="round"
|
|
82
|
+
/>
|
|
83
|
+
</svg>
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
renderStars() {
|
|
87
|
+
const { rating, maxRating, showHalfStars, interactive } = this.options;
|
|
88
|
+
const displayRating = interactive && this.hoverRating !== null ? this.hoverRating : rating;
|
|
89
|
+
const starSize = sizeMap[this.options.size];
|
|
90
|
+
let starsHTML = '';
|
|
91
|
+
for (let i = 1; i <= maxRating; i++) {
|
|
92
|
+
const filled = i <= Math.floor(displayRating);
|
|
93
|
+
const half = showHalfStars &&
|
|
94
|
+
i === Math.ceil(displayRating) &&
|
|
95
|
+
displayRating % 1 >= 0.25 &&
|
|
96
|
+
displayRating % 1 < 0.75;
|
|
97
|
+
const classes = `seekora-rating-star ${filled ? 'seekora-rating-star--filled' : 'seekora-rating-star--empty'} ${interactive ? 'seekora-rating-star--interactive' : ''}`;
|
|
98
|
+
starsHTML += `
|
|
99
|
+
<span
|
|
100
|
+
class="${classes}"
|
|
101
|
+
data-rating="${i}"
|
|
102
|
+
style="display: inline-block; width: ${starSize}px; height: ${starSize}px; cursor: ${interactive ? 'pointer' : 'default'};"
|
|
103
|
+
>
|
|
104
|
+
${this.createStarSVG(filled, half, starSize)}
|
|
105
|
+
</span>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
return `<div style="display: inline-flex; align-items: center; gap: 2px;">${starsHTML}</div>`;
|
|
109
|
+
}
|
|
110
|
+
render() {
|
|
111
|
+
const { variant, rating, reviewCount, showNumeric, showReviewCount, textColor, maxRating, className } = this.options;
|
|
112
|
+
const fontSize = fontSizeMap[this.options.size];
|
|
113
|
+
const clampedRating = Math.max(0, Math.min(maxRating, rating));
|
|
114
|
+
let html = '';
|
|
115
|
+
if (variant === 'stars-only') {
|
|
116
|
+
html = `
|
|
117
|
+
<div class="seekora-rating-display seekora-rating-display--stars-only ${className}"
|
|
118
|
+
style="display: inline-flex; align-items: center; gap: 2px;">
|
|
119
|
+
${this.renderStars()}
|
|
120
|
+
</div>
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
else if (variant === 'compact') {
|
|
124
|
+
html = `
|
|
125
|
+
<div class="seekora-rating-display seekora-rating-display--compact ${className}"
|
|
126
|
+
style="display: inline-flex; align-items: center; gap: 4px; font-size: ${fontSize};">
|
|
127
|
+
${this.renderStars()}
|
|
128
|
+
${showNumeric ? `<span class="seekora-rating-numeric" style="font-weight: 600; color: ${textColor};">${clampedRating.toFixed(1)}</span>` : ''}
|
|
129
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `<span class="seekora-rating-review-count" style="color: ${textColor};">(${this.options.reviewCountFormat(reviewCount)})</span>` : ''}
|
|
130
|
+
</div>
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
else if (variant === 'inline') {
|
|
134
|
+
html = `
|
|
135
|
+
<div class="seekora-rating-display seekora-rating-display--inline ${className}"
|
|
136
|
+
style="display: inline-flex; align-items: center; gap: 6px; font-size: ${fontSize};">
|
|
137
|
+
<span class="seekora-rating-numeric" style="font-weight: 600; color: var(--seekora-text-primary, #111827);">${clampedRating.toFixed(1)}</span>
|
|
138
|
+
${this.renderStars()}
|
|
139
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `<span class="seekora-rating-review-count" style="color: ${textColor};">(${this.options.reviewCountFormat(reviewCount)})</span>` : ''}
|
|
140
|
+
</div>
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
else if (variant === 'full') {
|
|
144
|
+
html = `
|
|
145
|
+
<div class="seekora-rating-display seekora-rating-display--full ${className}"
|
|
146
|
+
style="display: flex; flex-direction: column; gap: 4px; font-size: ${fontSize};">
|
|
147
|
+
<div style="display: flex; align-items: center; gap: 6px;">
|
|
148
|
+
${this.renderStars()}
|
|
149
|
+
<span class="seekora-rating-numeric" style="font-weight: 600; color: var(--seekora-text-primary, #111827);">${clampedRating.toFixed(1)}</span>
|
|
150
|
+
<span class="seekora-rating-max" style="color: ${textColor};">/ ${maxRating}</span>
|
|
151
|
+
</div>
|
|
152
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `
|
|
153
|
+
<span class="seekora-rating-review-text" style="font-size: 0.875em; color: ${textColor};">
|
|
154
|
+
Based on ${this.options.reviewCountFormat(reviewCount)} ${reviewCount === 1 ? 'review' : 'reviews'}
|
|
155
|
+
</span>
|
|
156
|
+
` : ''}
|
|
157
|
+
</div>
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
this.container.innerHTML = html;
|
|
161
|
+
if (this.options.interactive) {
|
|
162
|
+
this.attachEventListeners();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
attachEventListeners() {
|
|
166
|
+
const stars = this.container.querySelectorAll('.seekora-rating-star');
|
|
167
|
+
stars.forEach((star) => {
|
|
168
|
+
star.addEventListener('mouseenter', () => {
|
|
169
|
+
const rating = parseInt(star.dataset.rating || '0');
|
|
170
|
+
this.hoverRating = rating;
|
|
171
|
+
this.render();
|
|
172
|
+
});
|
|
173
|
+
star.addEventListener('click', () => {
|
|
174
|
+
const rating = parseInt(star.dataset.rating || '0');
|
|
175
|
+
this.hoverRating = null;
|
|
176
|
+
this.options.onRatingChange(rating);
|
|
177
|
+
this.render();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
this.container.addEventListener('mouseleave', () => {
|
|
181
|
+
this.hoverRating = null;
|
|
182
|
+
this.render();
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
update(options) {
|
|
186
|
+
this.options = { ...this.options, ...options };
|
|
187
|
+
this.render();
|
|
188
|
+
}
|
|
189
|
+
destroy() {
|
|
190
|
+
this.container.innerHTML = '';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Factory function for easier usage
|
|
194
|
+
function createRatingDisplay(container, options) {
|
|
195
|
+
return new RatingDisplay(container, options);
|
|
196
|
+
}
|
|
197
|
+
|
|
5
198
|
/**
|
|
6
199
|
* Default Theme
|
|
7
200
|
*/
|
|
@@ -4069,6 +4262,7 @@ exports.InfiniteHits = InfiniteHits;
|
|
|
4069
4262
|
exports.Pagination = Pagination;
|
|
4070
4263
|
exports.QuerySuggestions = QuerySuggestions;
|
|
4071
4264
|
exports.RangeInput = RangeInput;
|
|
4265
|
+
exports.RatingDisplay = RatingDisplay;
|
|
4072
4266
|
exports.SearchBar = SearchBar;
|
|
4073
4267
|
exports.SearchLayout = SearchLayout;
|
|
4074
4268
|
exports.SearchManager = SearchManager;
|
|
@@ -4076,6 +4270,7 @@ exports.SearchProvider = SearchProvider;
|
|
|
4076
4270
|
exports.SearchResults = SearchResults;
|
|
4077
4271
|
exports.SortBy = SortBy;
|
|
4078
4272
|
exports.Stats = Stats;
|
|
4273
|
+
exports.createRatingDisplay = createRatingDisplay;
|
|
4079
4274
|
exports.createTheme = createTheme;
|
|
4080
4275
|
exports.darkTheme = darkTheme;
|
|
4081
4276
|
exports.defaultTheme = defaultTheme;
|