@seekora-ai/ui-sdk-react 0.2.21 → 0.2.23
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/Facets.d.ts +4 -0
- package/dist/components/Facets.d.ts.map +1 -1
- package/dist/components/Facets.js +12 -15
- package/dist/components/HitsPerPage.d.ts.map +1 -1
- package/dist/components/HitsPerPage.js +21 -11
- package/dist/components/SortBy.d.ts.map +1 -1
- package/dist/components/SortBy.js +8 -11
- package/dist/components/primitives/CustomSelect.d.ts +40 -0
- package/dist/components/primitives/CustomSelect.d.ts.map +1 -0
- package/dist/components/primitives/CustomSelect.js +196 -0
- package/dist/components/primitives/ImageZoom.d.ts.map +1 -1
- package/dist/components/primitives/ImageZoom.js +37 -16
- package/dist/components/primitives/VariantSelector.d.ts.map +1 -1
- package/dist/components/primitives/VariantSelector.js +17 -24
- package/dist/components/primitives/index.d.ts +1 -0
- package/dist/components/primitives/index.d.ts.map +1 -1
- package/dist/components/primitives/index.js +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/src/index.d.ts +46 -2
- package/dist/src/index.esm.js +287 -78
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +287 -77
- package/dist/src/index.js.map +1 -1
- package/package.json +3 -3
package/dist/src/index.js
CHANGED
|
@@ -3114,6 +3114,201 @@ const Pagination = ({ results: resultsProp, currentPage: currentPageProp, itemsP
|
|
|
3114
3114
|
resolvedShowPageInfo && (React.createElement("li", { style: { marginLeft: theme.spacing.small } }, pageInfoElement)))));
|
|
3115
3115
|
};
|
|
3116
3116
|
|
|
3117
|
+
/**
|
|
3118
|
+
* CustomSelect — lightweight, accessible custom dropdown replacement for native <select>.
|
|
3119
|
+
*
|
|
3120
|
+
* CSS Variables (apply on a parent element to customize):
|
|
3121
|
+
* --seekora-select-bg — background color (default: #fff)
|
|
3122
|
+
* --seekora-select-color — text color (default: inherit)
|
|
3123
|
+
* --seekora-select-border — border color (default: rgba(128,128,128,0.3))
|
|
3124
|
+
* --seekora-select-hover-bg — option hover background (default: #f3f4f6)
|
|
3125
|
+
* --seekora-select-active-bg — selected option background (default: #eff6ff)
|
|
3126
|
+
* --seekora-select-active-color — selected option text color (default: inherit)
|
|
3127
|
+
* --seekora-select-radius — border radius (default: 6px)
|
|
3128
|
+
* --seekora-select-font-size — font size (default: 0.875rem)
|
|
3129
|
+
*/
|
|
3130
|
+
// ---------------------------------------------------------------------------
|
|
3131
|
+
// Component
|
|
3132
|
+
// ---------------------------------------------------------------------------
|
|
3133
|
+
const CustomSelect = ({ value, onChange, options, placeholder = 'Select...', className, style, theme: customTheme, 'aria-label': ariaLabel, disabled = false, }) => {
|
|
3134
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
3135
|
+
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
3136
|
+
const containerRef = React.useRef(null);
|
|
3137
|
+
const menuRef = React.useRef(null);
|
|
3138
|
+
const instanceId = React.useId();
|
|
3139
|
+
const t = customTheme || {};
|
|
3140
|
+
const selectedOption = options.find((o) => o.value === value);
|
|
3141
|
+
const displayLabel = selectedOption?.label ?? placeholder;
|
|
3142
|
+
// Close on click outside
|
|
3143
|
+
React.useEffect(() => {
|
|
3144
|
+
if (!isOpen)
|
|
3145
|
+
return;
|
|
3146
|
+
const handleMouseDown = (e) => {
|
|
3147
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
3148
|
+
setIsOpen(false);
|
|
3149
|
+
setActiveIndex(-1);
|
|
3150
|
+
}
|
|
3151
|
+
};
|
|
3152
|
+
document.addEventListener('mousedown', handleMouseDown);
|
|
3153
|
+
return () => document.removeEventListener('mousedown', handleMouseDown);
|
|
3154
|
+
}, [isOpen]);
|
|
3155
|
+
// Scroll active item into view
|
|
3156
|
+
React.useEffect(() => {
|
|
3157
|
+
if (!isOpen || activeIndex < 0 || !menuRef.current)
|
|
3158
|
+
return;
|
|
3159
|
+
const item = menuRef.current.children[activeIndex];
|
|
3160
|
+
item?.scrollIntoView?.({ block: 'nearest' });
|
|
3161
|
+
}, [activeIndex, isOpen]);
|
|
3162
|
+
const toggle = React.useCallback(() => {
|
|
3163
|
+
if (disabled)
|
|
3164
|
+
return;
|
|
3165
|
+
setIsOpen((prev) => {
|
|
3166
|
+
if (!prev) {
|
|
3167
|
+
// Opening — highlight current selection
|
|
3168
|
+
const idx = options.findIndex((o) => o.value === value);
|
|
3169
|
+
setActiveIndex(idx >= 0 ? idx : 0);
|
|
3170
|
+
}
|
|
3171
|
+
return !prev;
|
|
3172
|
+
});
|
|
3173
|
+
}, [disabled, options, value]);
|
|
3174
|
+
const selectOption = React.useCallback((opt) => {
|
|
3175
|
+
if (opt.disabled)
|
|
3176
|
+
return;
|
|
3177
|
+
onChange(opt.value);
|
|
3178
|
+
setIsOpen(false);
|
|
3179
|
+
setActiveIndex(-1);
|
|
3180
|
+
}, [onChange]);
|
|
3181
|
+
// Find next non-disabled index in given direction
|
|
3182
|
+
const findNextEnabled = (from, dir) => {
|
|
3183
|
+
let idx = from;
|
|
3184
|
+
for (let i = 0; i < options.length; i++) {
|
|
3185
|
+
idx += dir;
|
|
3186
|
+
if (idx < 0)
|
|
3187
|
+
idx = options.length - 1;
|
|
3188
|
+
if (idx >= options.length)
|
|
3189
|
+
idx = 0;
|
|
3190
|
+
if (!options[idx].disabled)
|
|
3191
|
+
return idx;
|
|
3192
|
+
}
|
|
3193
|
+
return from;
|
|
3194
|
+
};
|
|
3195
|
+
const handleKeyDown = React.useCallback((e) => {
|
|
3196
|
+
if (disabled)
|
|
3197
|
+
return;
|
|
3198
|
+
if (!isOpen) {
|
|
3199
|
+
if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(e.key)) {
|
|
3200
|
+
e.preventDefault();
|
|
3201
|
+
toggle();
|
|
3202
|
+
}
|
|
3203
|
+
return;
|
|
3204
|
+
}
|
|
3205
|
+
switch (e.key) {
|
|
3206
|
+
case 'ArrowDown':
|
|
3207
|
+
e.preventDefault();
|
|
3208
|
+
setActiveIndex((prev) => findNextEnabled(prev, 1));
|
|
3209
|
+
break;
|
|
3210
|
+
case 'ArrowUp':
|
|
3211
|
+
e.preventDefault();
|
|
3212
|
+
setActiveIndex((prev) => findNextEnabled(prev, -1));
|
|
3213
|
+
break;
|
|
3214
|
+
case 'Enter':
|
|
3215
|
+
case ' ':
|
|
3216
|
+
e.preventDefault();
|
|
3217
|
+
if (activeIndex >= 0 && !options[activeIndex].disabled) {
|
|
3218
|
+
selectOption(options[activeIndex]);
|
|
3219
|
+
}
|
|
3220
|
+
break;
|
|
3221
|
+
case 'Escape':
|
|
3222
|
+
e.preventDefault();
|
|
3223
|
+
setIsOpen(false);
|
|
3224
|
+
setActiveIndex(-1);
|
|
3225
|
+
break;
|
|
3226
|
+
case 'Home':
|
|
3227
|
+
e.preventDefault();
|
|
3228
|
+
setActiveIndex(findNextEnabled(-1, 1));
|
|
3229
|
+
break;
|
|
3230
|
+
case 'End':
|
|
3231
|
+
e.preventDefault();
|
|
3232
|
+
setActiveIndex(findNextEnabled(options.length, -1));
|
|
3233
|
+
break;
|
|
3234
|
+
case 'Tab':
|
|
3235
|
+
setIsOpen(false);
|
|
3236
|
+
setActiveIndex(-1);
|
|
3237
|
+
break;
|
|
3238
|
+
}
|
|
3239
|
+
}, [disabled, isOpen, activeIndex, options, toggle, selectOption]);
|
|
3240
|
+
const menuId = `seekora-select-menu-${instanceId}`;
|
|
3241
|
+
return (React.createElement("div", { ref: containerRef, className: clsx('seekora-select', className), style: { position: 'relative', display: 'inline-block', ...style }, onKeyDown: handleKeyDown },
|
|
3242
|
+
React.createElement("button", { type: "button", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": menuId, "aria-label": ariaLabel, "aria-activedescendant": isOpen && activeIndex >= 0
|
|
3243
|
+
? `${menuId}-opt-${activeIndex}`
|
|
3244
|
+
: undefined, disabled: disabled, onClick: toggle, className: clsx('seekora-select__trigger', t.trigger), style: {
|
|
3245
|
+
display: 'flex',
|
|
3246
|
+
alignItems: 'center',
|
|
3247
|
+
justifyContent: 'space-between',
|
|
3248
|
+
gap: 8,
|
|
3249
|
+
width: '100%',
|
|
3250
|
+
padding: '8px 12px',
|
|
3251
|
+
fontSize: 'var(--seekora-select-font-size, 0.875rem)',
|
|
3252
|
+
lineHeight: 1.4,
|
|
3253
|
+
border: '1px solid var(--seekora-select-border, rgba(128,128,128,0.3))',
|
|
3254
|
+
borderRadius: 'var(--seekora-select-radius, 6px)',
|
|
3255
|
+
backgroundColor: 'var(--seekora-select-bg, #fff)',
|
|
3256
|
+
color: 'var(--seekora-select-color, inherit)',
|
|
3257
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
3258
|
+
outline: 'none',
|
|
3259
|
+
textAlign: 'left',
|
|
3260
|
+
fontFamily: 'inherit',
|
|
3261
|
+
opacity: disabled ? 0.5 : 1,
|
|
3262
|
+
} },
|
|
3263
|
+
React.createElement("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, displayLabel),
|
|
3264
|
+
React.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: {
|
|
3265
|
+
flexShrink: 0,
|
|
3266
|
+
transition: 'transform 0.15s ease',
|
|
3267
|
+
transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
|
|
3268
|
+
} },
|
|
3269
|
+
React.createElement("path", { d: "M2.5 4.5L6 8L9.5 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }))),
|
|
3270
|
+
isOpen && (React.createElement("div", { ref: menuRef, id: menuId, role: "listbox", className: clsx('seekora-select__menu', t.menu), style: {
|
|
3271
|
+
position: 'absolute',
|
|
3272
|
+
top: '100%',
|
|
3273
|
+
left: 0,
|
|
3274
|
+
right: 0,
|
|
3275
|
+
zIndex: 9999,
|
|
3276
|
+
marginTop: 4,
|
|
3277
|
+
padding: '4px 0',
|
|
3278
|
+
border: '1px solid var(--seekora-select-border, rgba(128,128,128,0.3))',
|
|
3279
|
+
borderRadius: 'var(--seekora-select-radius, 6px)',
|
|
3280
|
+
backgroundColor: 'var(--seekora-select-bg, #fff)',
|
|
3281
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
|
3282
|
+
maxHeight: 220,
|
|
3283
|
+
overflowY: 'auto',
|
|
3284
|
+
} }, options.map((opt, idx) => {
|
|
3285
|
+
const isSelected = opt.value === value;
|
|
3286
|
+
const isHighlighted = idx === activeIndex;
|
|
3287
|
+
return (React.createElement("div", { key: opt.value, id: `${menuId}-opt-${idx}`, role: "option", "aria-selected": isSelected, "aria-disabled": opt.disabled || undefined, className: clsx('seekora-select__option', t.option, isSelected && 'seekora-select__option--selected', isHighlighted && (t.optionActive || 'seekora-select__option--highlighted'), opt.disabled && (t.optionDisabled || 'seekora-select__option--disabled')), onMouseEnter: () => !opt.disabled && setActiveIndex(idx), onMouseDown: (e) => {
|
|
3288
|
+
e.preventDefault(); // Prevent blur
|
|
3289
|
+
if (!opt.disabled)
|
|
3290
|
+
selectOption(opt);
|
|
3291
|
+
}, style: {
|
|
3292
|
+
padding: '6px 12px',
|
|
3293
|
+
fontSize: 'var(--seekora-select-font-size, 0.875rem)',
|
|
3294
|
+
cursor: opt.disabled ? 'not-allowed' : 'pointer',
|
|
3295
|
+
backgroundColor: isHighlighted
|
|
3296
|
+
? 'var(--seekora-select-hover-bg, #f3f4f6)'
|
|
3297
|
+
: isSelected
|
|
3298
|
+
? 'var(--seekora-select-active-bg, #eff6ff)'
|
|
3299
|
+
: 'transparent',
|
|
3300
|
+
color: opt.disabled
|
|
3301
|
+
? 'rgba(128,128,128,0.5)'
|
|
3302
|
+
: isSelected
|
|
3303
|
+
? 'var(--seekora-select-active-color, inherit)'
|
|
3304
|
+
: 'var(--seekora-select-color, inherit)',
|
|
3305
|
+
fontWeight: isSelected ? 500 : 400,
|
|
3306
|
+
opacity: opt.disabled ? 0.5 : 1,
|
|
3307
|
+
transition: 'background-color 0.1s ease',
|
|
3308
|
+
} }, opt.label));
|
|
3309
|
+
})))));
|
|
3310
|
+
};
|
|
3311
|
+
|
|
3117
3312
|
/**
|
|
3118
3313
|
* SortBy Component
|
|
3119
3314
|
*
|
|
@@ -3217,18 +3412,14 @@ const SortBy = ({ options, value: valueProp, defaultValue, onSortChange, renderS
|
|
|
3217
3412
|
}
|
|
3218
3413
|
return (React.createElement("div", { className: clsx(sortByTheme.container, className), style: { ...cssVarStyle, ...style } },
|
|
3219
3414
|
labelElement,
|
|
3220
|
-
React.createElement(
|
|
3221
|
-
padding,
|
|
3222
|
-
paddingRight: theme.spacing.medium,
|
|
3223
|
-
fontSize,
|
|
3224
|
-
border: '1px solid var(--seekora-sort-border)',
|
|
3225
|
-
borderRadius,
|
|
3226
|
-
backgroundColor: 'var(--seekora-sort-bg)',
|
|
3227
|
-
color: 'var(--seekora-sort-color)',
|
|
3228
|
-
cursor: 'pointer',
|
|
3229
|
-
outline: 'none',
|
|
3415
|
+
React.createElement(CustomSelect, { value: value, onChange: applyValue, options: options, placeholder: placeholder, "aria-label": label || 'Sort results', className: clsx(sortByTheme.select), style: {
|
|
3230
3416
|
width: '100%',
|
|
3231
|
-
|
|
3417
|
+
'--seekora-select-font-size': fontSize,
|
|
3418
|
+
'--seekora-select-border': 'var(--seekora-sort-border)',
|
|
3419
|
+
'--seekora-select-radius': borderRadius,
|
|
3420
|
+
'--seekora-select-bg': 'var(--seekora-sort-bg)',
|
|
3421
|
+
'--seekora-select-color': 'var(--seekora-sort-color)',
|
|
3422
|
+
} })));
|
|
3232
3423
|
}
|
|
3233
3424
|
// ------ Button group variant -------------------------------------------
|
|
3234
3425
|
if (variant === 'button-group') {
|
|
@@ -3678,7 +3869,7 @@ const CSS_VAR_DEFAULTS = {
|
|
|
3678
3869
|
// ---------------------------------------------------------------------------
|
|
3679
3870
|
// Component
|
|
3680
3871
|
// ---------------------------------------------------------------------------
|
|
3681
|
-
const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, renderFacet, renderFacetItem, maxItems = 10, showMore = true, className, style, theme: customTheme, variant = 'checkbox', searchable = false, showCounts = true, colorMap, defaultCollapsed = false, size = 'medium', facetRanges, useFiltersApi = false, disjunctiveFacets, }) => {
|
|
3872
|
+
const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, renderFacet, renderFacetItem, maxItems = 10, showMore = true, className, style, theme: customTheme, variant = 'checkbox', searchable = false, showCounts = true, colorMap, defaultCollapsed = false, size = 'medium', facetRanges, useFiltersApi = false, disjunctiveFacets, hideEmptyFacets = true, defaultCollapsedFields, }) => {
|
|
3682
3873
|
const { theme } = useSearchContext();
|
|
3683
3874
|
const { results: stateResults, refinements, addRefinement, removeRefinement } = useSearchState();
|
|
3684
3875
|
const facetsTheme = customTheme || {};
|
|
@@ -3755,7 +3946,10 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3755
3946
|
});
|
|
3756
3947
|
return extracted;
|
|
3757
3948
|
};
|
|
3758
|
-
const
|
|
3949
|
+
const rawFacetList = extractFacets();
|
|
3950
|
+
const facets = hideEmptyFacets
|
|
3951
|
+
? rawFacetList.filter(f => f.items.length > 0 || f.stats != null)
|
|
3952
|
+
: rawFacetList;
|
|
3759
3953
|
// -------------------------------------------------------------------
|
|
3760
3954
|
// Handlers
|
|
3761
3955
|
// -------------------------------------------------------------------
|
|
@@ -3792,17 +3986,21 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3792
3986
|
}));
|
|
3793
3987
|
};
|
|
3794
3988
|
/** For collapsible variant — determine if a facet group is open. */
|
|
3989
|
+
const isFieldDefaultCollapsed = (field) => {
|
|
3990
|
+
if (defaultCollapsedFields?.includes(field))
|
|
3991
|
+
return true;
|
|
3992
|
+
return defaultCollapsed;
|
|
3993
|
+
};
|
|
3795
3994
|
const isFacetGroupOpen = (field) => {
|
|
3796
3995
|
if (field in expandedFacets) {
|
|
3797
3996
|
return expandedFacets[field];
|
|
3798
3997
|
}
|
|
3799
|
-
|
|
3800
|
-
return !defaultCollapsed;
|
|
3998
|
+
return !isFieldDefaultCollapsed(field);
|
|
3801
3999
|
};
|
|
3802
4000
|
const toggleCollapsible = (field) => {
|
|
3803
4001
|
setExpandedFacets((prev) => ({
|
|
3804
4002
|
...prev,
|
|
3805
|
-
[field]: !(prev[field] ?? !
|
|
4003
|
+
[field]: !(prev[field] ?? !isFieldDefaultCollapsed(field)),
|
|
3806
4004
|
}));
|
|
3807
4005
|
};
|
|
3808
4006
|
const getSearchTerm = (field) => searchTerms[field] || '';
|
|
@@ -4048,8 +4246,6 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
4048
4246
|
borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
|
|
4049
4247
|
} },
|
|
4050
4248
|
React.createElement("h3", { className: facetsTheme.facetTitle, style: {
|
|
4051
|
-
fontSize: theme.typography.fontSize.large,
|
|
4052
|
-
fontWeight: 'bold',
|
|
4053
4249
|
margin: 0,
|
|
4054
4250
|
marginBottom: theme.spacing.medium,
|
|
4055
4251
|
color: theme.colors.text,
|
|
@@ -4073,8 +4269,6 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
4073
4269
|
borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
|
|
4074
4270
|
} },
|
|
4075
4271
|
React.createElement("h3", { className: facetsTheme.facetTitle, style: {
|
|
4076
|
-
fontSize: theme.typography.fontSize.large,
|
|
4077
|
-
fontWeight: 'bold',
|
|
4078
4272
|
margin: 0,
|
|
4079
4273
|
marginBottom: theme.spacing.medium,
|
|
4080
4274
|
color: theme.colors.text,
|
|
@@ -4120,8 +4314,6 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
4120
4314
|
textAlign: 'left',
|
|
4121
4315
|
} },
|
|
4122
4316
|
React.createElement("span", { className: facetsTheme.facetTitle, style: {
|
|
4123
|
-
fontSize: theme.typography.fontSize.large,
|
|
4124
|
-
fontWeight: 'bold',
|
|
4125
4317
|
color: theme.colors.text,
|
|
4126
4318
|
flex: 1,
|
|
4127
4319
|
} }, facet.label || facet.field),
|
|
@@ -4240,8 +4432,6 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
4240
4432
|
borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
|
|
4241
4433
|
} },
|
|
4242
4434
|
React.createElement("h3", { className: facetsTheme.facetTitle, style: {
|
|
4243
|
-
fontSize: theme.typography.fontSize.large,
|
|
4244
|
-
fontWeight: 'bold',
|
|
4245
4435
|
margin: 0,
|
|
4246
4436
|
marginBottom: theme.spacing.medium,
|
|
4247
4437
|
color: theme.colors.text,
|
|
@@ -4322,8 +4512,6 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
4322
4512
|
} },
|
|
4323
4513
|
React.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: theme.spacing.small } },
|
|
4324
4514
|
React.createElement("h3", { className: facetsTheme.facetTitle, style: {
|
|
4325
|
-
fontSize: theme.typography.fontSize.large,
|
|
4326
|
-
fontWeight: 'bold',
|
|
4327
4515
|
margin: 0,
|
|
4328
4516
|
color: theme.colors.text,
|
|
4329
4517
|
} }, facet.label || facet.field),
|
|
@@ -5449,19 +5637,28 @@ const HitsPerPage = ({ items, onHitsPerPageChange, renderSelect, className, styl
|
|
|
5449
5637
|
fontSize: theme.typography.fontSize.medium,
|
|
5450
5638
|
color: theme.colors.text,
|
|
5451
5639
|
} }, label)),
|
|
5452
|
-
React.createElement(
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5640
|
+
React.createElement(CustomSelect, { value: String(value), onChange: (val) => {
|
|
5641
|
+
const newValue = parseInt(val, 10);
|
|
5642
|
+
setInternalValue(newValue);
|
|
5643
|
+
if (syncWithState) {
|
|
5644
|
+
stateManager.setItemsPerPage(newValue, false);
|
|
5645
|
+
setPage(1, true);
|
|
5646
|
+
}
|
|
5647
|
+
if (onHitsPerPageChange) {
|
|
5648
|
+
onHitsPerPageChange(newValue);
|
|
5649
|
+
}
|
|
5650
|
+
}, options: items.map((item) => ({
|
|
5651
|
+
value: String(item.value),
|
|
5652
|
+
label: item.label,
|
|
5653
|
+
})), "aria-label": "Results per page", className: hitsPerPageTheme.select, style: {
|
|
5654
|
+
'--seekora-select-font-size': theme.typography.fontSize.medium,
|
|
5655
|
+
'--seekora-select-border': theme.colors.border,
|
|
5656
|
+
'--seekora-select-radius': typeof theme.borderRadius === 'string'
|
|
5458
5657
|
? theme.borderRadius
|
|
5459
5658
|
: theme.borderRadius.medium,
|
|
5460
|
-
|
|
5461
|
-
color: theme.colors.text,
|
|
5462
|
-
|
|
5463
|
-
outline: 'none',
|
|
5464
|
-
}, "aria-label": "Results per page" }, items.map((item) => (React.createElement("option", { key: item.value, value: item.value, className: hitsPerPageTheme.option }, item.label))))));
|
|
5659
|
+
'--seekora-select-bg': theme.colors.background,
|
|
5660
|
+
'--seekora-select-color': theme.colors.text,
|
|
5661
|
+
} })));
|
|
5465
5662
|
};
|
|
5466
5663
|
|
|
5467
5664
|
/**
|
|
@@ -9730,13 +9927,30 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
9730
9927
|
objectFit: 'cover',
|
|
9731
9928
|
display: 'block',
|
|
9732
9929
|
};
|
|
9930
|
+
// Compute the indicator rectangle (what portion of the image the zoom panel shows).
|
|
9931
|
+
// indW / containerW = 1 / zoomLevel (the panel shows 1/zoomLevel of the image width).
|
|
9932
|
+
// indH is derived from the zoom panel's aspect ratio so it's consistent with what the
|
|
9933
|
+
// panel actually renders — no need for the image's natural dimensions.
|
|
9934
|
+
const getIndicatorRect = React.useCallback(() => {
|
|
9935
|
+
if (!containerRef.current)
|
|
9936
|
+
return { indL: 0, indT: 0, indW: 0, indH: 0 };
|
|
9937
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
9938
|
+
const indW = rect.width / zoomLevel;
|
|
9939
|
+
const indH = (zoomPanelSize.height / zoomPanelSize.width) * rect.width / zoomLevel;
|
|
9940
|
+
const indL = Math.max(0, Math.min(rect.width - indW, cursorPos.x - indW / 2));
|
|
9941
|
+
const indT = Math.max(0, Math.min(rect.height - indH, cursorPos.y - indH / 2));
|
|
9942
|
+
return { indL, indT, indW, indH };
|
|
9943
|
+
}, [cursorPos, zoomLevel, zoomPanelSize]);
|
|
9733
9944
|
// Calculate zoom panel background position (Amazon-style)
|
|
9734
9945
|
const getZoomPanelStyle = () => {
|
|
9735
9946
|
if (!containerRef.current || !imageLoaded)
|
|
9736
9947
|
return { display: 'none' };
|
|
9737
9948
|
const rect = containerRef.current.getBoundingClientRect();
|
|
9738
|
-
const
|
|
9739
|
-
|
|
9949
|
+
const { indL, indT, indW, indH } = getIndicatorRect();
|
|
9950
|
+
// bgPos is derived from the clamped indicator position, not the raw cursor.
|
|
9951
|
+
// At indL=0 → bgPosX=0% (show left), at indL=containerW-indW → bgPosX=100% (show right).
|
|
9952
|
+
const bgPosX = (rect.width - indW) > 0 ? (indL / (rect.width - indW)) * 100 : 0;
|
|
9953
|
+
const bgPosY = (rect.height - indH) > 0 ? (indT / (rect.height - indH)) * 100 : 0;
|
|
9740
9954
|
// Calculate available space in all directions
|
|
9741
9955
|
const viewportWidth = window.innerWidth;
|
|
9742
9956
|
const viewportHeight = window.innerHeight;
|
|
@@ -9864,19 +10078,22 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
9864
10078
|
} }, "\uD83D\uDD0D")),
|
|
9865
10079
|
supportsLens && isHovering && imageLoaded && (React.createElement("div", { style: getLensStyle() },
|
|
9866
10080
|
React.createElement("img", { src: src, alt: "", style: getLensImageStyle() }))),
|
|
9867
|
-
supportsHover && isHovering && imageLoaded && containerRef.current && (
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
10081
|
+
supportsHover && isHovering && imageLoaded && containerRef.current && (() => {
|
|
10082
|
+
const { indL, indT, indW, indH } = getIndicatorRect();
|
|
10083
|
+
return (React.createElement("div", { style: {
|
|
10084
|
+
position: 'absolute',
|
|
10085
|
+
left: indL,
|
|
10086
|
+
top: indT,
|
|
10087
|
+
width: indW,
|
|
10088
|
+
height: indH,
|
|
10089
|
+
border: 'var(--seekora-hover-area-border, 2px solid rgba(0,0,0,0.3))',
|
|
10090
|
+
backgroundColor: 'var(--seekora-hover-area-bg, rgba(255,255,255,0.1))',
|
|
10091
|
+
pointerEvents: 'none',
|
|
10092
|
+
zIndex: 50,
|
|
10093
|
+
} }));
|
|
10094
|
+
})()),
|
|
10095
|
+
supportsHover && isHovering && imageLoaded && typeof document !== 'undefined' && reactDom.createPortal(React.createElement("div", { style: getZoomPanelStyle() }), document.body),
|
|
10096
|
+
isLightboxOpen && typeof document !== 'undefined' && reactDom.createPortal(React.createElement("div", { className: "seekora-image-zoom-lightbox", style: {
|
|
9880
10097
|
position: 'fixed',
|
|
9881
10098
|
top: 0,
|
|
9882
10099
|
left: 0,
|
|
@@ -10031,7 +10248,7 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
10031
10248
|
backgroundColor: 'var(--seekora-lightbox-instructions-bg, rgba(0,0,0,0.5))',
|
|
10032
10249
|
padding: '8px 16px',
|
|
10033
10250
|
borderRadius: 12,
|
|
10034
|
-
} }, hasMultipleImages ? 'Use arrow keys or click thumbnails to navigate • ESC to close' : 'Click outside or press ESC to close')))));
|
|
10251
|
+
} }, hasMultipleImages ? 'Use arrow keys or click thumbnails to navigate • ESC to close' : 'Click outside or press ESC to close')), document.body)));
|
|
10035
10252
|
}
|
|
10036
10253
|
|
|
10037
10254
|
/**
|
|
@@ -11862,30 +12079,22 @@ function VariantSelector({ options, variants, selections, onSelectionChange, opt
|
|
|
11862
12079
|
} },
|
|
11863
12080
|
option.name,
|
|
11864
12081
|
selected && (React.createElement("span", { style: { fontWeight: 400, marginLeft: 6, color: 'var(--seekora-text-secondary, inherit)' } }, selected))),
|
|
11865
|
-
mode === 'dropdown' ? (React.createElement("
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
option.
|
|
11881
|
-
option.values.map((value) => {
|
|
11882
|
-
const available = showAvailability
|
|
11883
|
-
? getAvailability(option.name, value, options, variants, selections)
|
|
11884
|
-
: true;
|
|
11885
|
-
return (React.createElement("option", { key: value, value: value, disabled: !available },
|
|
11886
|
-
value,
|
|
11887
|
-
!available ? ' (Unavailable)' : ''));
|
|
11888
|
-
}))) : (React.createElement("div", { className: "seekora-variant-buttons", style: { display: 'flex', flexWrap: 'wrap', gap: 8 } }, option.values.map((value) => {
|
|
12082
|
+
mode === 'dropdown' ? (React.createElement("div", { onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation() },
|
|
12083
|
+
React.createElement(CustomSelect, { className: "seekora-variant-dropdown", value: selected ?? '', onChange: (val) => onSelectionChange(option.name, val), placeholder: `Select ${option.name}`, "aria-label": `Select ${option.name}`, options: option.values.map((val) => {
|
|
12084
|
+
const available = showAvailability
|
|
12085
|
+
? getAvailability(option.name, val, options, variants, selections)
|
|
12086
|
+
: true;
|
|
12087
|
+
return {
|
|
12088
|
+
value: val,
|
|
12089
|
+
label: available ? val : `${val} (Unavailable)`,
|
|
12090
|
+
disabled: !available,
|
|
12091
|
+
};
|
|
12092
|
+
}), style: {
|
|
12093
|
+
minWidth: 120,
|
|
12094
|
+
'--seekora-select-border': 'var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
12095
|
+
'--seekora-select-bg': 'var(--seekora-bg-surface, transparent)',
|
|
12096
|
+
'--seekora-select-color': 'var(--seekora-text-primary, inherit)',
|
|
12097
|
+
} }))) : (React.createElement("div", { className: "seekora-variant-buttons", style: { display: 'flex', flexWrap: 'wrap', gap: 8 } }, option.values.map((value) => {
|
|
11889
12098
|
const isActive = selected === value;
|
|
11890
12099
|
const available = showAvailability
|
|
11891
12100
|
? getAvailability(option.name, value, options, variants, selections)
|
|
@@ -18657,6 +18866,7 @@ exports.Breadcrumb = Breadcrumb;
|
|
|
18657
18866
|
exports.CategoriesTabs = CategoriesTabs;
|
|
18658
18867
|
exports.ClearRefinements = ClearRefinements;
|
|
18659
18868
|
exports.CurrentRefinements = CurrentRefinements;
|
|
18869
|
+
exports.CustomSelect = CustomSelect;
|
|
18660
18870
|
exports.DocSearch = DocSearch;
|
|
18661
18871
|
exports.DocSearchButton = DocSearchButton;
|
|
18662
18872
|
exports.DropdownPanel = DropdownPanel;
|