@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/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("select", { value: value, onChange: handleChange, className: clsx(sortByTheme.select), style: {
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
- }, "aria-label": label || 'Sort results' }, options.map((option) => (React.createElement("option", { key: option.value, value: option.value, className: sortByTheme.option }, option.label))))));
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 facets = extractFacets();
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
- // Default based on defaultCollapsed prop
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] ?? !defaultCollapsed),
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("select", { value: value, onChange: handleChange, className: hitsPerPageTheme.select, style: {
5443
- padding: theme.spacing.small,
5444
- paddingRight: theme.spacing.medium,
5445
- fontSize: theme.typography.fontSize.medium,
5446
- border: `1px solid ${theme.colors.border}`,
5447
- borderRadius: typeof theme.borderRadius === 'string'
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
- backgroundColor: theme.colors.background,
5451
- color: theme.colors.text,
5452
- cursor: 'pointer',
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 bgPosX = (cursorPos.x / rect.width) * 100;
9729
- const bgPosY = (cursorPos.y / rect.height) * 100;
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 && (React.createElement("div", { style: {
9858
- position: 'absolute',
9859
- left: cursorPos.x - 75,
9860
- top: cursorPos.y - 75,
9861
- width: 150,
9862
- height: 150,
9863
- border: 'var(--seekora-hover-area-border, 2px solid rgba(0,0,0,0.3))',
9864
- backgroundColor: 'var(--seekora-hover-area-bg, rgba(255,255,255,0.1))',
9865
- pointerEvents: 'none',
9866
- zIndex: 50,
9867
- } })),
9868
- supportsHover && isHovering && imageLoaded && (React.createElement("div", { style: getZoomPanelStyle() }))),
9869
- isLightboxOpen && (React.createElement("div", { className: "seekora-image-zoom-lightbox", style: {
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("select", { className: "seekora-variant-dropdown", value: selected ?? '', onChange: (e) => {
11856
- e.stopPropagation();
11857
- onSelectionChange(option.name, e.target.value);
11858
- }, onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), style: {
11859
- padding: '8px 12px',
11860
- fontSize: '0.875rem',
11861
- borderRadius: 6,
11862
- border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
11863
- backgroundColor: 'var(--seekora-bg-surface, transparent)',
11864
- color: 'var(--seekora-text-primary, inherit)',
11865
- cursor: 'pointer',
11866
- minWidth: 120,
11867
- } },
11868
- React.createElement("option", { value: "" },
11869
- "Select ",
11870
- option.name),
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;