@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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RatingDisplay - Vanilla JS
|
|
3
|
+
*
|
|
4
|
+
* Star rating display with review count and multiple variants
|
|
5
|
+
*/
|
|
6
|
+
export type RatingVariant = 'stars-only' | 'compact' | 'full' | 'inline';
|
|
7
|
+
export type RatingSize = 'small' | 'medium' | 'large';
|
|
8
|
+
export interface RatingDisplayOptions {
|
|
9
|
+
rating: number;
|
|
10
|
+
reviewCount?: number;
|
|
11
|
+
variant?: RatingVariant;
|
|
12
|
+
size?: RatingSize;
|
|
13
|
+
maxRating?: number;
|
|
14
|
+
showNumeric?: boolean;
|
|
15
|
+
showHalfStars?: boolean;
|
|
16
|
+
interactive?: boolean;
|
|
17
|
+
onRatingChange?: (rating: number) => void;
|
|
18
|
+
starColor?: string;
|
|
19
|
+
emptyStarColor?: string;
|
|
20
|
+
textColor?: string;
|
|
21
|
+
showReviewCount?: boolean;
|
|
22
|
+
reviewCountFormat?: (count: number) => string;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class RatingDisplay {
|
|
26
|
+
private container;
|
|
27
|
+
private options;
|
|
28
|
+
private hoverRating;
|
|
29
|
+
constructor(containerOrSelector: string | HTMLElement, options: RatingDisplayOptions);
|
|
30
|
+
private defaultReviewCountFormat;
|
|
31
|
+
private createStarSVG;
|
|
32
|
+
private renderStars;
|
|
33
|
+
private render;
|
|
34
|
+
private attachEventListeners;
|
|
35
|
+
update(options: Partial<RatingDisplayOptions>): void;
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|
|
38
|
+
export declare function createRatingDisplay(container: string | HTMLElement, options: RatingDisplayOptions): RatingDisplay;
|
|
39
|
+
//# sourceMappingURL=rating-display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating-display.d.ts","sourceRoot":"","sources":["../../src/components/rating-display.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AACzE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgCD,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,WAAW,CAAuB;gBAE9B,mBAAmB,EAAE,MAAM,GAAG,WAAW,EAAE,OAAO,EAAE,oBAAoB;IA6BpF,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,WAAW;IA6BnB,OAAO,CAAC,MAAM;IAyDd,OAAO,CAAC,oBAAoB;IAwBrB,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,IAAI;IAKpD,OAAO,IAAI,IAAI;CAGvB;AAGD,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAAG,WAAW,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,aAAa,CAEf"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RatingDisplay - Vanilla JS
|
|
3
|
+
*
|
|
4
|
+
* Star rating display with review count and multiple variants
|
|
5
|
+
*/
|
|
6
|
+
const sizeMap = {
|
|
7
|
+
small: 14,
|
|
8
|
+
medium: 18,
|
|
9
|
+
large: 24,
|
|
10
|
+
};
|
|
11
|
+
const fontSizeMap = {
|
|
12
|
+
small: '0.75rem',
|
|
13
|
+
medium: '0.875rem',
|
|
14
|
+
large: '1rem',
|
|
15
|
+
};
|
|
16
|
+
export class RatingDisplay {
|
|
17
|
+
constructor(containerOrSelector, options) {
|
|
18
|
+
this.hoverRating = null;
|
|
19
|
+
this.container = typeof containerOrSelector === 'string'
|
|
20
|
+
? document.querySelector(containerOrSelector)
|
|
21
|
+
: containerOrSelector;
|
|
22
|
+
if (!this.container) {
|
|
23
|
+
throw new Error('RatingDisplay: Container element not found');
|
|
24
|
+
}
|
|
25
|
+
this.options = {
|
|
26
|
+
variant: 'compact',
|
|
27
|
+
size: 'medium',
|
|
28
|
+
maxRating: 5,
|
|
29
|
+
showNumeric: false,
|
|
30
|
+
showHalfStars: true,
|
|
31
|
+
interactive: false,
|
|
32
|
+
starColor: '#f59e0b',
|
|
33
|
+
emptyStarColor: '#d1d5db',
|
|
34
|
+
textColor: 'var(--seekora-text-secondary, #6b7280)',
|
|
35
|
+
showReviewCount: true,
|
|
36
|
+
onRatingChange: () => { },
|
|
37
|
+
reviewCountFormat: this.defaultReviewCountFormat,
|
|
38
|
+
className: '',
|
|
39
|
+
...options,
|
|
40
|
+
};
|
|
41
|
+
this.render();
|
|
42
|
+
}
|
|
43
|
+
defaultReviewCountFormat(count) {
|
|
44
|
+
if (count >= 1000000)
|
|
45
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
46
|
+
if (count >= 1000)
|
|
47
|
+
return `${(count / 1000).toFixed(1)}K`;
|
|
48
|
+
return count.toString();
|
|
49
|
+
}
|
|
50
|
+
createStarSVG(filled, half, size) {
|
|
51
|
+
const { starColor, emptyStarColor } = this.options;
|
|
52
|
+
if (half) {
|
|
53
|
+
return `
|
|
54
|
+
<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
55
|
+
<defs>
|
|
56
|
+
<linearGradient id="half-fill-${Math.random()}">
|
|
57
|
+
<stop offset="50%" stop-color="${starColor}" />
|
|
58
|
+
<stop offset="50%" stop-color="${emptyStarColor}" />
|
|
59
|
+
</linearGradient>
|
|
60
|
+
</defs>
|
|
61
|
+
<path
|
|
62
|
+
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"
|
|
63
|
+
fill="url(#half-fill-${Math.random()})"
|
|
64
|
+
stroke="${starColor}"
|
|
65
|
+
stroke-width="1"
|
|
66
|
+
/>
|
|
67
|
+
</svg>
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
return `
|
|
71
|
+
<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="${filled ? starColor : 'none'}" xmlns="http://www.w3.org/2000/svg">
|
|
72
|
+
<path
|
|
73
|
+
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"
|
|
74
|
+
stroke="${filled ? starColor : emptyStarColor}"
|
|
75
|
+
stroke-width="1.5"
|
|
76
|
+
stroke-linecap="round"
|
|
77
|
+
stroke-linejoin="round"
|
|
78
|
+
/>
|
|
79
|
+
</svg>
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
renderStars() {
|
|
83
|
+
const { rating, maxRating, showHalfStars, interactive } = this.options;
|
|
84
|
+
const displayRating = interactive && this.hoverRating !== null ? this.hoverRating : rating;
|
|
85
|
+
const starSize = sizeMap[this.options.size];
|
|
86
|
+
let starsHTML = '';
|
|
87
|
+
for (let i = 1; i <= maxRating; i++) {
|
|
88
|
+
const filled = i <= Math.floor(displayRating);
|
|
89
|
+
const half = showHalfStars &&
|
|
90
|
+
i === Math.ceil(displayRating) &&
|
|
91
|
+
displayRating % 1 >= 0.25 &&
|
|
92
|
+
displayRating % 1 < 0.75;
|
|
93
|
+
const classes = `seekora-rating-star ${filled ? 'seekora-rating-star--filled' : 'seekora-rating-star--empty'} ${interactive ? 'seekora-rating-star--interactive' : ''}`;
|
|
94
|
+
starsHTML += `
|
|
95
|
+
<span
|
|
96
|
+
class="${classes}"
|
|
97
|
+
data-rating="${i}"
|
|
98
|
+
style="display: inline-block; width: ${starSize}px; height: ${starSize}px; cursor: ${interactive ? 'pointer' : 'default'};"
|
|
99
|
+
>
|
|
100
|
+
${this.createStarSVG(filled, half, starSize)}
|
|
101
|
+
</span>
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
return `<div style="display: inline-flex; align-items: center; gap: 2px;">${starsHTML}</div>`;
|
|
105
|
+
}
|
|
106
|
+
render() {
|
|
107
|
+
const { variant, rating, reviewCount, showNumeric, showReviewCount, textColor, maxRating, className } = this.options;
|
|
108
|
+
const fontSize = fontSizeMap[this.options.size];
|
|
109
|
+
const clampedRating = Math.max(0, Math.min(maxRating, rating));
|
|
110
|
+
let html = '';
|
|
111
|
+
if (variant === 'stars-only') {
|
|
112
|
+
html = `
|
|
113
|
+
<div class="seekora-rating-display seekora-rating-display--stars-only ${className}"
|
|
114
|
+
style="display: inline-flex; align-items: center; gap: 2px;">
|
|
115
|
+
${this.renderStars()}
|
|
116
|
+
</div>
|
|
117
|
+
`;
|
|
118
|
+
}
|
|
119
|
+
else if (variant === 'compact') {
|
|
120
|
+
html = `
|
|
121
|
+
<div class="seekora-rating-display seekora-rating-display--compact ${className}"
|
|
122
|
+
style="display: inline-flex; align-items: center; gap: 4px; font-size: ${fontSize};">
|
|
123
|
+
${this.renderStars()}
|
|
124
|
+
${showNumeric ? `<span class="seekora-rating-numeric" style="font-weight: 600; color: ${textColor};">${clampedRating.toFixed(1)}</span>` : ''}
|
|
125
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `<span class="seekora-rating-review-count" style="color: ${textColor};">(${this.options.reviewCountFormat(reviewCount)})</span>` : ''}
|
|
126
|
+
</div>
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
else if (variant === 'inline') {
|
|
130
|
+
html = `
|
|
131
|
+
<div class="seekora-rating-display seekora-rating-display--inline ${className}"
|
|
132
|
+
style="display: inline-flex; align-items: center; gap: 6px; font-size: ${fontSize};">
|
|
133
|
+
<span class="seekora-rating-numeric" style="font-weight: 600; color: var(--seekora-text-primary, #111827);">${clampedRating.toFixed(1)}</span>
|
|
134
|
+
${this.renderStars()}
|
|
135
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `<span class="seekora-rating-review-count" style="color: ${textColor};">(${this.options.reviewCountFormat(reviewCount)})</span>` : ''}
|
|
136
|
+
</div>
|
|
137
|
+
`;
|
|
138
|
+
}
|
|
139
|
+
else if (variant === 'full') {
|
|
140
|
+
html = `
|
|
141
|
+
<div class="seekora-rating-display seekora-rating-display--full ${className}"
|
|
142
|
+
style="display: flex; flex-direction: column; gap: 4px; font-size: ${fontSize};">
|
|
143
|
+
<div style="display: flex; align-items: center; gap: 6px;">
|
|
144
|
+
${this.renderStars()}
|
|
145
|
+
<span class="seekora-rating-numeric" style="font-weight: 600; color: var(--seekora-text-primary, #111827);">${clampedRating.toFixed(1)}</span>
|
|
146
|
+
<span class="seekora-rating-max" style="color: ${textColor};">/ ${maxRating}</span>
|
|
147
|
+
</div>
|
|
148
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `
|
|
149
|
+
<span class="seekora-rating-review-text" style="font-size: 0.875em; color: ${textColor};">
|
|
150
|
+
Based on ${this.options.reviewCountFormat(reviewCount)} ${reviewCount === 1 ? 'review' : 'reviews'}
|
|
151
|
+
</span>
|
|
152
|
+
` : ''}
|
|
153
|
+
</div>
|
|
154
|
+
`;
|
|
155
|
+
}
|
|
156
|
+
this.container.innerHTML = html;
|
|
157
|
+
if (this.options.interactive) {
|
|
158
|
+
this.attachEventListeners();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
attachEventListeners() {
|
|
162
|
+
const stars = this.container.querySelectorAll('.seekora-rating-star');
|
|
163
|
+
stars.forEach((star) => {
|
|
164
|
+
star.addEventListener('mouseenter', () => {
|
|
165
|
+
const rating = parseInt(star.dataset.rating || '0');
|
|
166
|
+
this.hoverRating = rating;
|
|
167
|
+
this.render();
|
|
168
|
+
});
|
|
169
|
+
star.addEventListener('click', () => {
|
|
170
|
+
const rating = parseInt(star.dataset.rating || '0');
|
|
171
|
+
this.hoverRating = null;
|
|
172
|
+
this.options.onRatingChange(rating);
|
|
173
|
+
this.render();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
this.container.addEventListener('mouseleave', () => {
|
|
177
|
+
this.hoverRating = null;
|
|
178
|
+
this.render();
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
update(options) {
|
|
182
|
+
this.options = { ...this.options, ...options };
|
|
183
|
+
this.render();
|
|
184
|
+
}
|
|
185
|
+
destroy() {
|
|
186
|
+
this.container.innerHTML = '';
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Factory function for easier usage
|
|
190
|
+
export function createRatingDisplay(container, options) {
|
|
191
|
+
return new RatingDisplay(container, options);
|
|
192
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,45 @@ import * as _seekora_ai_ui_sdk_types from '@seekora-ai/ui-sdk-types';
|
|
|
5
5
|
import { Theme, ThemeConfig, ViewMode, FieldMapping, ResultItem } from '@seekora-ai/ui-sdk-types';
|
|
6
6
|
export { FieldMapping, ResultItem, SuggestionItem, Theme, ThemeConfig, ViewMode } from '@seekora-ai/ui-sdk-types';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* RatingDisplay - Vanilla JS
|
|
10
|
+
*
|
|
11
|
+
* Star rating display with review count and multiple variants
|
|
12
|
+
*/
|
|
13
|
+
type RatingVariant = 'stars-only' | 'compact' | 'full' | 'inline';
|
|
14
|
+
type RatingSize = 'small' | 'medium' | 'large';
|
|
15
|
+
interface RatingDisplayOptions {
|
|
16
|
+
rating: number;
|
|
17
|
+
reviewCount?: number;
|
|
18
|
+
variant?: RatingVariant;
|
|
19
|
+
size?: RatingSize;
|
|
20
|
+
maxRating?: number;
|
|
21
|
+
showNumeric?: boolean;
|
|
22
|
+
showHalfStars?: boolean;
|
|
23
|
+
interactive?: boolean;
|
|
24
|
+
onRatingChange?: (rating: number) => void;
|
|
25
|
+
starColor?: string;
|
|
26
|
+
emptyStarColor?: string;
|
|
27
|
+
textColor?: string;
|
|
28
|
+
showReviewCount?: boolean;
|
|
29
|
+
reviewCountFormat?: (count: number) => string;
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
declare class RatingDisplay {
|
|
33
|
+
private container;
|
|
34
|
+
private options;
|
|
35
|
+
private hoverRating;
|
|
36
|
+
constructor(containerOrSelector: string | HTMLElement, options: RatingDisplayOptions);
|
|
37
|
+
private defaultReviewCountFormat;
|
|
38
|
+
private createStarSVG;
|
|
39
|
+
private renderStars;
|
|
40
|
+
private render;
|
|
41
|
+
private attachEventListeners;
|
|
42
|
+
update(options: Partial<RatingDisplayOptions>): void;
|
|
43
|
+
destroy(): void;
|
|
44
|
+
}
|
|
45
|
+
declare function createRatingDisplay(container: string | HTMLElement, options: RatingDisplayOptions): RatingDisplay;
|
|
46
|
+
|
|
8
47
|
/**
|
|
9
48
|
* SearchProvider
|
|
10
49
|
*
|
|
@@ -669,5 +708,5 @@ declare const minimalTheme: Theme;
|
|
|
669
708
|
|
|
670
709
|
declare const createTheme: (config: ThemeConfig) => _seekora_ai_ui_sdk_types.Theme;
|
|
671
710
|
|
|
672
|
-
export { ClearRefinements, CurrentRefinements, Facets, HitsPerPage, InfiniteHits, Pagination, QuerySuggestions, RangeInput, SearchBar, SearchLayout, SearchManager, SearchProvider, SearchResults, SortBy, Stats, createTheme, darkTheme, defaultTheme, minimalTheme };
|
|
673
|
-
export type { ClearRefinementsOptions, CurrentRefinementsOptions, Facet, FacetItem, FacetsOptions, HitsPerPageItem, HitsPerPageOptions, InfiniteHitsOptions, PaginationOptions, QuerySuggestionsOptions, RangeInputOptions, Refinement, SearchBarOptions, SearchLayoutOptions, SearchManagerConfig, SearchProviderConfig, SearchResultsOptions, SearchState, SortByOptions, SortOption, StatsOptions };
|
|
711
|
+
export { ClearRefinements, CurrentRefinements, Facets, HitsPerPage, InfiniteHits, Pagination, QuerySuggestions, RangeInput, RatingDisplay, SearchBar, SearchLayout, SearchManager, SearchProvider, SearchResults, SortBy, Stats, createRatingDisplay, createTheme, darkTheme, defaultTheme, minimalTheme };
|
|
712
|
+
export type { ClearRefinementsOptions, CurrentRefinementsOptions, Facet, FacetItem, FacetsOptions, HitsPerPageItem, HitsPerPageOptions, InfiniteHitsOptions, PaginationOptions, QuerySuggestionsOptions, RangeInputOptions, RatingDisplayOptions, RatingSize, RatingVariant, Refinement, SearchBarOptions, SearchLayoutOptions, SearchManagerConfig, SearchProviderConfig, SearchResultsOptions, SearchState, SortByOptions, SortOption, StatsOptions };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,YAAY,EACV,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,aAAa,EACb,UAAU,GACX,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,aAAa,EACb,KAAK,EACL,SAAS,GACV,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,yBAAyB,EACzB,UAAU,GACX,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACV,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,mBAAmB,EACnB,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EACV,KAAK,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,YAAY,EACV,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,aAAa,EACb,UAAU,GACX,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,aAAa,EACb,KAAK,EACL,SAAS,GACV,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,yBAAyB,EACzB,UAAU,GACX,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACV,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,mBAAmB,EACnB,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EACV,KAAK,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,199 @@
|
|
|
1
1
|
import { createTheme as createTheme$1, log, SearchStateManager, extractField, formatPrice } from '@seekora-ai/ui-sdk-core';
|
|
2
2
|
export { getHighlightedValue, getSnippetedValue, highlightQuery, mergeThemes, parseHighlightedParts, parseQueryHighlightParts, stripHighlightTags } from '@seekora-ai/ui-sdk-core';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* RatingDisplay - Vanilla JS
|
|
6
|
+
*
|
|
7
|
+
* Star rating display with review count and multiple variants
|
|
8
|
+
*/
|
|
9
|
+
const sizeMap = {
|
|
10
|
+
small: 14,
|
|
11
|
+
medium: 18,
|
|
12
|
+
large: 24,
|
|
13
|
+
};
|
|
14
|
+
const fontSizeMap = {
|
|
15
|
+
small: '0.75rem',
|
|
16
|
+
medium: '0.875rem',
|
|
17
|
+
large: '1rem',
|
|
18
|
+
};
|
|
19
|
+
class RatingDisplay {
|
|
20
|
+
constructor(containerOrSelector, options) {
|
|
21
|
+
this.hoverRating = null;
|
|
22
|
+
this.container = typeof containerOrSelector === 'string'
|
|
23
|
+
? document.querySelector(containerOrSelector)
|
|
24
|
+
: containerOrSelector;
|
|
25
|
+
if (!this.container) {
|
|
26
|
+
throw new Error('RatingDisplay: Container element not found');
|
|
27
|
+
}
|
|
28
|
+
this.options = {
|
|
29
|
+
variant: 'compact',
|
|
30
|
+
size: 'medium',
|
|
31
|
+
maxRating: 5,
|
|
32
|
+
showNumeric: false,
|
|
33
|
+
showHalfStars: true,
|
|
34
|
+
interactive: false,
|
|
35
|
+
starColor: '#f59e0b',
|
|
36
|
+
emptyStarColor: '#d1d5db',
|
|
37
|
+
textColor: 'var(--seekora-text-secondary, #6b7280)',
|
|
38
|
+
showReviewCount: true,
|
|
39
|
+
onRatingChange: () => { },
|
|
40
|
+
reviewCountFormat: this.defaultReviewCountFormat,
|
|
41
|
+
className: '',
|
|
42
|
+
...options,
|
|
43
|
+
};
|
|
44
|
+
this.render();
|
|
45
|
+
}
|
|
46
|
+
defaultReviewCountFormat(count) {
|
|
47
|
+
if (count >= 1000000)
|
|
48
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
49
|
+
if (count >= 1000)
|
|
50
|
+
return `${(count / 1000).toFixed(1)}K`;
|
|
51
|
+
return count.toString();
|
|
52
|
+
}
|
|
53
|
+
createStarSVG(filled, half, size) {
|
|
54
|
+
const { starColor, emptyStarColor } = this.options;
|
|
55
|
+
if (half) {
|
|
56
|
+
return `
|
|
57
|
+
<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
58
|
+
<defs>
|
|
59
|
+
<linearGradient id="half-fill-${Math.random()}">
|
|
60
|
+
<stop offset="50%" stop-color="${starColor}" />
|
|
61
|
+
<stop offset="50%" stop-color="${emptyStarColor}" />
|
|
62
|
+
</linearGradient>
|
|
63
|
+
</defs>
|
|
64
|
+
<path
|
|
65
|
+
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"
|
|
66
|
+
fill="url(#half-fill-${Math.random()})"
|
|
67
|
+
stroke="${starColor}"
|
|
68
|
+
stroke-width="1"
|
|
69
|
+
/>
|
|
70
|
+
</svg>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
return `
|
|
74
|
+
<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="${filled ? starColor : 'none'}" xmlns="http://www.w3.org/2000/svg">
|
|
75
|
+
<path
|
|
76
|
+
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"
|
|
77
|
+
stroke="${filled ? starColor : emptyStarColor}"
|
|
78
|
+
stroke-width="1.5"
|
|
79
|
+
stroke-linecap="round"
|
|
80
|
+
stroke-linejoin="round"
|
|
81
|
+
/>
|
|
82
|
+
</svg>
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
renderStars() {
|
|
86
|
+
const { rating, maxRating, showHalfStars, interactive } = this.options;
|
|
87
|
+
const displayRating = interactive && this.hoverRating !== null ? this.hoverRating : rating;
|
|
88
|
+
const starSize = sizeMap[this.options.size];
|
|
89
|
+
let starsHTML = '';
|
|
90
|
+
for (let i = 1; i <= maxRating; i++) {
|
|
91
|
+
const filled = i <= Math.floor(displayRating);
|
|
92
|
+
const half = showHalfStars &&
|
|
93
|
+
i === Math.ceil(displayRating) &&
|
|
94
|
+
displayRating % 1 >= 0.25 &&
|
|
95
|
+
displayRating % 1 < 0.75;
|
|
96
|
+
const classes = `seekora-rating-star ${filled ? 'seekora-rating-star--filled' : 'seekora-rating-star--empty'} ${interactive ? 'seekora-rating-star--interactive' : ''}`;
|
|
97
|
+
starsHTML += `
|
|
98
|
+
<span
|
|
99
|
+
class="${classes}"
|
|
100
|
+
data-rating="${i}"
|
|
101
|
+
style="display: inline-block; width: ${starSize}px; height: ${starSize}px; cursor: ${interactive ? 'pointer' : 'default'};"
|
|
102
|
+
>
|
|
103
|
+
${this.createStarSVG(filled, half, starSize)}
|
|
104
|
+
</span>
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
return `<div style="display: inline-flex; align-items: center; gap: 2px;">${starsHTML}</div>`;
|
|
108
|
+
}
|
|
109
|
+
render() {
|
|
110
|
+
const { variant, rating, reviewCount, showNumeric, showReviewCount, textColor, maxRating, className } = this.options;
|
|
111
|
+
const fontSize = fontSizeMap[this.options.size];
|
|
112
|
+
const clampedRating = Math.max(0, Math.min(maxRating, rating));
|
|
113
|
+
let html = '';
|
|
114
|
+
if (variant === 'stars-only') {
|
|
115
|
+
html = `
|
|
116
|
+
<div class="seekora-rating-display seekora-rating-display--stars-only ${className}"
|
|
117
|
+
style="display: inline-flex; align-items: center; gap: 2px;">
|
|
118
|
+
${this.renderStars()}
|
|
119
|
+
</div>
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
else if (variant === 'compact') {
|
|
123
|
+
html = `
|
|
124
|
+
<div class="seekora-rating-display seekora-rating-display--compact ${className}"
|
|
125
|
+
style="display: inline-flex; align-items: center; gap: 4px; font-size: ${fontSize};">
|
|
126
|
+
${this.renderStars()}
|
|
127
|
+
${showNumeric ? `<span class="seekora-rating-numeric" style="font-weight: 600; color: ${textColor};">${clampedRating.toFixed(1)}</span>` : ''}
|
|
128
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `<span class="seekora-rating-review-count" style="color: ${textColor};">(${this.options.reviewCountFormat(reviewCount)})</span>` : ''}
|
|
129
|
+
</div>
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
else if (variant === 'inline') {
|
|
133
|
+
html = `
|
|
134
|
+
<div class="seekora-rating-display seekora-rating-display--inline ${className}"
|
|
135
|
+
style="display: inline-flex; align-items: center; gap: 6px; font-size: ${fontSize};">
|
|
136
|
+
<span class="seekora-rating-numeric" style="font-weight: 600; color: var(--seekora-text-primary, #111827);">${clampedRating.toFixed(1)}</span>
|
|
137
|
+
${this.renderStars()}
|
|
138
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `<span class="seekora-rating-review-count" style="color: ${textColor};">(${this.options.reviewCountFormat(reviewCount)})</span>` : ''}
|
|
139
|
+
</div>
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
else if (variant === 'full') {
|
|
143
|
+
html = `
|
|
144
|
+
<div class="seekora-rating-display seekora-rating-display--full ${className}"
|
|
145
|
+
style="display: flex; flex-direction: column; gap: 4px; font-size: ${fontSize};">
|
|
146
|
+
<div style="display: flex; align-items: center; gap: 6px;">
|
|
147
|
+
${this.renderStars()}
|
|
148
|
+
<span class="seekora-rating-numeric" style="font-weight: 600; color: var(--seekora-text-primary, #111827);">${clampedRating.toFixed(1)}</span>
|
|
149
|
+
<span class="seekora-rating-max" style="color: ${textColor};">/ ${maxRating}</span>
|
|
150
|
+
</div>
|
|
151
|
+
${showReviewCount && reviewCount != null && reviewCount > 0 ? `
|
|
152
|
+
<span class="seekora-rating-review-text" style="font-size: 0.875em; color: ${textColor};">
|
|
153
|
+
Based on ${this.options.reviewCountFormat(reviewCount)} ${reviewCount === 1 ? 'review' : 'reviews'}
|
|
154
|
+
</span>
|
|
155
|
+
` : ''}
|
|
156
|
+
</div>
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
this.container.innerHTML = html;
|
|
160
|
+
if (this.options.interactive) {
|
|
161
|
+
this.attachEventListeners();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
attachEventListeners() {
|
|
165
|
+
const stars = this.container.querySelectorAll('.seekora-rating-star');
|
|
166
|
+
stars.forEach((star) => {
|
|
167
|
+
star.addEventListener('mouseenter', () => {
|
|
168
|
+
const rating = parseInt(star.dataset.rating || '0');
|
|
169
|
+
this.hoverRating = rating;
|
|
170
|
+
this.render();
|
|
171
|
+
});
|
|
172
|
+
star.addEventListener('click', () => {
|
|
173
|
+
const rating = parseInt(star.dataset.rating || '0');
|
|
174
|
+
this.hoverRating = null;
|
|
175
|
+
this.options.onRatingChange(rating);
|
|
176
|
+
this.render();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
this.container.addEventListener('mouseleave', () => {
|
|
180
|
+
this.hoverRating = null;
|
|
181
|
+
this.render();
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
update(options) {
|
|
185
|
+
this.options = { ...this.options, ...options };
|
|
186
|
+
this.render();
|
|
187
|
+
}
|
|
188
|
+
destroy() {
|
|
189
|
+
this.container.innerHTML = '';
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Factory function for easier usage
|
|
193
|
+
function createRatingDisplay(container, options) {
|
|
194
|
+
return new RatingDisplay(container, options);
|
|
195
|
+
}
|
|
196
|
+
|
|
4
197
|
/**
|
|
5
198
|
* Default Theme
|
|
6
199
|
*/
|
|
@@ -4032,5 +4225,5 @@ const minimalTheme = {
|
|
|
4032
4225
|
},
|
|
4033
4226
|
};
|
|
4034
4227
|
|
|
4035
|
-
export { ClearRefinements, CurrentRefinements, Facets, HitsPerPage, InfiniteHits, Pagination, QuerySuggestions, RangeInput, SearchBar, SearchLayout, SearchManager, SearchProvider, SearchResults, SortBy, Stats, createTheme, darkTheme, defaultTheme, minimalTheme };
|
|
4228
|
+
export { ClearRefinements, CurrentRefinements, Facets, HitsPerPage, InfiniteHits, Pagination, QuerySuggestions, RangeInput, RatingDisplay, SearchBar, SearchLayout, SearchManager, SearchProvider, SearchResults, SortBy, Stats, createRatingDisplay, createTheme, darkTheme, defaultTheme, minimalTheme };
|
|
4036
4229
|
//# sourceMappingURL=index.esm.js.map
|