@seekora-ai/ui-sdk-react 0.2.22 → 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 -5
- 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 -68
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +287 -67
- 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] || '';
|
|
@@ -5439,19 +5637,28 @@ const HitsPerPage = ({ items, onHitsPerPageChange, renderSelect, className, styl
|
|
|
5439
5637
|
fontSize: theme.typography.fontSize.medium,
|
|
5440
5638
|
color: theme.colors.text,
|
|
5441
5639
|
} }, label)),
|
|
5442
|
-
React.createElement(
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
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'
|
|
5448
5657
|
? theme.borderRadius
|
|
5449
5658
|
: theme.borderRadius.medium,
|
|
5450
|
-
|
|
5451
|
-
color: theme.colors.text,
|
|
5452
|
-
|
|
5453
|
-
outline: 'none',
|
|
5454
|
-
}, "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
|
+
} })));
|
|
5455
5662
|
};
|
|
5456
5663
|
|
|
5457
5664
|
/**
|
|
@@ -9720,13 +9927,30 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
9720
9927
|
objectFit: 'cover',
|
|
9721
9928
|
display: 'block',
|
|
9722
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]);
|
|
9723
9944
|
// Calculate zoom panel background position (Amazon-style)
|
|
9724
9945
|
const getZoomPanelStyle = () => {
|
|
9725
9946
|
if (!containerRef.current || !imageLoaded)
|
|
9726
9947
|
return { display: 'none' };
|
|
9727
9948
|
const rect = containerRef.current.getBoundingClientRect();
|
|
9728
|
-
const
|
|
9729
|
-
|
|
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;
|
|
9730
9954
|
// Calculate available space in all directions
|
|
9731
9955
|
const viewportWidth = window.innerWidth;
|
|
9732
9956
|
const viewportHeight = window.innerHeight;
|
|
@@ -9854,19 +10078,22 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
9854
10078
|
} }, "\uD83D\uDD0D")),
|
|
9855
10079
|
supportsLens && isHovering && imageLoaded && (React.createElement("div", { style: getLensStyle() },
|
|
9856
10080
|
React.createElement("img", { src: src, alt: "", style: getLensImageStyle() }))),
|
|
9857
|
-
supportsHover && isHovering && imageLoaded && containerRef.current && (
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
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: {
|
|
9870
10097
|
position: 'fixed',
|
|
9871
10098
|
top: 0,
|
|
9872
10099
|
left: 0,
|
|
@@ -10021,7 +10248,7 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
10021
10248
|
backgroundColor: 'var(--seekora-lightbox-instructions-bg, rgba(0,0,0,0.5))',
|
|
10022
10249
|
padding: '8px 16px',
|
|
10023
10250
|
borderRadius: 12,
|
|
10024
|
-
} }, 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)));
|
|
10025
10252
|
}
|
|
10026
10253
|
|
|
10027
10254
|
/**
|
|
@@ -11852,30 +12079,22 @@ function VariantSelector({ options, variants, selections, onSelectionChange, opt
|
|
|
11852
12079
|
} },
|
|
11853
12080
|
option.name,
|
|
11854
12081
|
selected && (React.createElement("span", { style: { fontWeight: 400, marginLeft: 6, color: 'var(--seekora-text-secondary, inherit)' } }, selected))),
|
|
11855
|
-
mode === 'dropdown' ? (React.createElement("
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
option.
|
|
11871
|
-
option.values.map((value) => {
|
|
11872
|
-
const available = showAvailability
|
|
11873
|
-
? getAvailability(option.name, value, options, variants, selections)
|
|
11874
|
-
: true;
|
|
11875
|
-
return (React.createElement("option", { key: value, value: value, disabled: !available },
|
|
11876
|
-
value,
|
|
11877
|
-
!available ? ' (Unavailable)' : ''));
|
|
11878
|
-
}))) : (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) => {
|
|
11879
12098
|
const isActive = selected === value;
|
|
11880
12099
|
const available = showAvailability
|
|
11881
12100
|
? getAvailability(option.name, value, options, variants, selections)
|
|
@@ -18647,6 +18866,7 @@ exports.Breadcrumb = Breadcrumb;
|
|
|
18647
18866
|
exports.CategoriesTabs = CategoriesTabs;
|
|
18648
18867
|
exports.ClearRefinements = ClearRefinements;
|
|
18649
18868
|
exports.CurrentRefinements = CurrentRefinements;
|
|
18869
|
+
exports.CustomSelect = CustomSelect;
|
|
18650
18870
|
exports.DocSearch = DocSearch;
|
|
18651
18871
|
exports.DocSearchButton = DocSearchButton;
|
|
18652
18872
|
exports.DropdownPanel = DropdownPanel;
|