@seekora-ai/ui-sdk-react 0.2.12 → 0.2.14

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.
Files changed (102) hide show
  1. package/dist/components/CurrentRefinements.d.ts +22 -2
  2. package/dist/components/CurrentRefinements.d.ts.map +1 -1
  3. package/dist/components/CurrentRefinements.js +199 -47
  4. package/dist/components/Facets.d.ts +30 -1
  5. package/dist/components/Facets.d.ts.map +1 -1
  6. package/dist/components/Facets.js +418 -46
  7. package/dist/components/HierarchicalMenu.d.ts.map +1 -1
  8. package/dist/components/HierarchicalMenu.js +112 -4
  9. package/dist/components/InfiniteHits.d.ts +2 -0
  10. package/dist/components/InfiniteHits.d.ts.map +1 -1
  11. package/dist/components/InfiniteHits.js +6 -3
  12. package/dist/components/Pagination.d.ts +47 -1
  13. package/dist/components/Pagination.d.ts.map +1 -1
  14. package/dist/components/Pagination.js +166 -28
  15. package/dist/components/QuerySuggestions.d.ts +2 -0
  16. package/dist/components/QuerySuggestions.d.ts.map +1 -1
  17. package/dist/components/QuerySuggestions.js +4 -3
  18. package/dist/components/QuerySuggestionsDropdown.d.ts +1 -1
  19. package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -1
  20. package/dist/components/QuerySuggestionsDropdown.js +4 -4
  21. package/dist/components/RangeSlider.d.ts.map +1 -1
  22. package/dist/components/RangeSlider.js +49 -2
  23. package/dist/components/Recommendations.d.ts +6 -0
  24. package/dist/components/Recommendations.d.ts.map +1 -1
  25. package/dist/components/Recommendations.js +12 -6
  26. package/dist/components/RichQuerySuggestions.d.ts +11 -0
  27. package/dist/components/RichQuerySuggestions.d.ts.map +1 -1
  28. package/dist/components/RichQuerySuggestions.js +2 -3
  29. package/dist/components/SearchBar.d.ts +18 -0
  30. package/dist/components/SearchBar.d.ts.map +1 -1
  31. package/dist/components/SearchBar.js +134 -24
  32. package/dist/components/SearchProvider.d.ts +8 -1
  33. package/dist/components/SearchProvider.d.ts.map +1 -1
  34. package/dist/components/SearchProvider.js +16 -4
  35. package/dist/components/SearchResults.d.ts +12 -0
  36. package/dist/components/SearchResults.d.ts.map +1 -1
  37. package/dist/components/SearchResults.js +11 -5
  38. package/dist/components/SortBy.d.ts +44 -4
  39. package/dist/components/SortBy.d.ts.map +1 -1
  40. package/dist/components/SortBy.js +154 -29
  41. package/dist/components/Stats.d.ts +14 -0
  42. package/dist/components/Stats.d.ts.map +1 -1
  43. package/dist/components/Stats.js +172 -23
  44. package/dist/components/section-primitives/SectionItemGrid.d.ts +3 -1
  45. package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -1
  46. package/dist/components/section-primitives/SectionItemGrid.js +3 -2
  47. package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -1
  48. package/dist/components/suggestions/AmazonDropdown.js +4 -6
  49. package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -1
  50. package/dist/components/suggestions/GoogleDropdown.js +4 -8
  51. package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -1
  52. package/dist/components/suggestions/MinimalDropdown.js +4 -6
  53. package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -1
  54. package/dist/components/suggestions/MobileSheetDropdown.js +4 -6
  55. package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -1
  56. package/dist/components/suggestions/PinterestDropdown.js +4 -8
  57. package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -1
  58. package/dist/components/suggestions/ShopifyDropdown.js +4 -6
  59. package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -1
  60. package/dist/components/suggestions/SpotlightDropdown.js +4 -6
  61. package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -1
  62. package/dist/components/suggestions/SuggestionSearchBar.js +1 -0
  63. package/dist/components/suggestions/types.d.ts +2 -0
  64. package/dist/components/suggestions/types.d.ts.map +1 -1
  65. package/dist/components/suggestions/utils.d.ts +10 -1
  66. package/dist/components/suggestions/utils.d.ts.map +1 -1
  67. package/dist/components/suggestions/utils.js +36 -0
  68. package/dist/components/suggestions-primitives/SuggestionList.d.ts +8 -1
  69. package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -1
  70. package/dist/components/suggestions-primitives/SuggestionList.js +7 -4
  71. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts.map +1 -1
  72. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.js +0 -2
  73. package/dist/components/suggestions-primitives/highlightMarkup.d.ts +16 -4
  74. package/dist/components/suggestions-primitives/highlightMarkup.d.ts.map +1 -1
  75. package/dist/components/suggestions-primitives/highlightMarkup.js +42 -4
  76. package/dist/docsearch/components/Results.d.ts +3 -1
  77. package/dist/docsearch/components/Results.d.ts.map +1 -1
  78. package/dist/docsearch/components/Results.js +6 -2
  79. package/dist/hooks/useClickTracking.d.ts +36 -0
  80. package/dist/hooks/useClickTracking.d.ts.map +1 -0
  81. package/dist/hooks/useClickTracking.js +96 -0
  82. package/dist/hooks/useExperiment.d.ts +25 -0
  83. package/dist/hooks/useExperiment.d.ts.map +1 -0
  84. package/dist/hooks/useExperiment.js +146 -0
  85. package/dist/hooks/useKeyboardNavigation.d.ts +51 -0
  86. package/dist/hooks/useKeyboardNavigation.d.ts.map +1 -0
  87. package/dist/hooks/useKeyboardNavigation.js +113 -0
  88. package/dist/hooks/useQuerySuggestions.d.ts.map +1 -1
  89. package/dist/hooks/useQuerySuggestions.js +19 -3
  90. package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -1
  91. package/dist/hooks/useQuerySuggestionsEnhanced.js +25 -7
  92. package/dist/hooks/useSuggestionsAnalytics.d.ts.map +1 -1
  93. package/dist/hooks/useSuggestionsAnalytics.js +6 -1
  94. package/dist/index.d.ts +4 -1
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.umd.js +1 -1
  97. package/dist/src/index.d.ts +249 -19
  98. package/dist/src/index.esm.js +1659 -305
  99. package/dist/src/index.esm.js.map +1 -1
  100. package/dist/src/index.js +1658 -304
  101. package/dist/src/index.js.map +1 -1
  102. package/package.json +3 -3
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * CurrentRefinements Component
3
3
  *
4
- * Displays currently active filters/refinements with ability to clear them
4
+ * Displays currently active filters/refinements with ability to clear them.
5
+ * Supports StateManager auto-sync, display variants, layout modes, and animations.
5
6
  */
6
7
  import React from 'react';
7
8
  export interface Refinement {
@@ -18,9 +19,20 @@ export interface CurrentRefinementsTheme {
18
19
  value?: string;
19
20
  clearButton?: string;
20
21
  clearAllButton?: string;
22
+ /** Variant-specific class slots */
23
+ chip?: string;
24
+ tag?: string;
25
+ pill?: string;
26
+ badge?: string;
27
+ group?: string;
28
+ groupLabel?: string;
21
29
  }
30
+ /** Display variant for refinement items */
31
+ export type RefinementVariant = 'chips' | 'tags' | 'pills' | 'badges' | 'text-list';
32
+ /** Layout variant for the container */
33
+ export type RefinementLayout = 'horizontal' | 'vertical' | 'grouped';
22
34
  export interface CurrentRefinementsProps {
23
- /** Current refinements */
35
+ /** Current refinements (if not provided, auto-reads from StateManager) */
24
36
  refinements?: Refinement[];
25
37
  /** Callback when a refinement is cleared */
26
38
  onRefinementClear?: (field: string, value: string) => void;
@@ -30,6 +42,14 @@ export interface CurrentRefinementsProps {
30
42
  renderRefinement?: (refinement: Refinement, index: number) => React.ReactNode;
31
43
  /** Show "Clear all" button */
32
44
  showClearAll?: boolean;
45
+ /** Display variant (default: 'chips') */
46
+ variant?: RefinementVariant;
47
+ /** Layout mode (default: 'horizontal') */
48
+ layout?: RefinementLayout;
49
+ /** Per-field color mapping */
50
+ fieldColors?: Record<string, string>;
51
+ /** Custom close icon renderer */
52
+ renderCloseIcon?: () => React.ReactNode;
33
53
  /** Custom className */
34
54
  className?: string;
35
55
  /** Custom styles */
@@ -1 +1 @@
1
- {"version":3,"file":"CurrentRefinements.d.ts","sourceRoot":"","sources":["../../src/components/CurrentRefinements.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,0BAA0B;IAC1B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,8BAA8B;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,uBAAuB,CAAC;CACjC;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAmIhE,CAAC"}
1
+ {"version":3,"file":"CurrentRefinements.d.ts","sourceRoot":"","sources":["../../src/components/CurrentRefinements.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAK3D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,2CAA2C;AAC3C,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEpF,uCAAuC;AACvC,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,8BAA8B;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,0CAA0C;IAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,iCAAiC;IACjC,eAAe,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACxC,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,uBAAuB,CAAC;CACjC;AA0FD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA2OhE,CAAC"}
@@ -1,75 +1,226 @@
1
1
  /**
2
2
  * CurrentRefinements Component
3
3
  *
4
- * Displays currently active filters/refinements with ability to clear them
4
+ * Displays currently active filters/refinements with ability to clear them.
5
+ * Supports StateManager auto-sync, display variants, layout modes, and animations.
5
6
  */
6
- import React from 'react';
7
+ import React, { useState, useEffect, useRef } from 'react';
7
8
  import { useSearchContext } from './SearchProvider';
9
+ import { useSearchState } from '../hooks/useSearchState';
8
10
  import { clsx } from 'clsx';
9
- export const CurrentRefinements = ({ refinements = [], onRefinementClear, onClearAll, renderRefinement, showClearAll = true, className, style, theme: customTheme, }) => {
11
+ /** Get variant-specific styles */
12
+ const getVariantStyles = (variant, themeColors, themeSpacing, themeBorderRadius, fieldColor) => {
13
+ const baseBg = fieldColor || `var(--seekora-refinement-bg, ${themeColors.hover})`;
14
+ const baseColor = `var(--seekora-refinement-color, ${themeColors.text})`;
15
+ const baseBorder = `var(--seekora-refinement-border, ${themeColors.border})`;
16
+ switch (variant) {
17
+ case 'tags':
18
+ return {
19
+ display: 'inline-flex',
20
+ alignItems: 'center',
21
+ padding: `2px ${themeSpacing.medium}`,
22
+ backgroundColor: baseBg,
23
+ border: `1px solid ${baseBorder}`,
24
+ borderRadius: `var(--seekora-refinement-radius, 4px)`,
25
+ fontSize: '12px',
26
+ color: baseColor,
27
+ fontWeight: 500,
28
+ };
29
+ case 'pills':
30
+ return {
31
+ display: 'inline-flex',
32
+ alignItems: 'center',
33
+ padding: `${themeSpacing.small} ${themeSpacing.medium}`,
34
+ backgroundColor: baseBg,
35
+ border: 'none',
36
+ borderRadius: `var(--seekora-refinement-radius, 9999px)`,
37
+ fontSize: '13px',
38
+ color: baseColor,
39
+ };
40
+ case 'badges':
41
+ return {
42
+ display: 'inline-flex',
43
+ alignItems: 'center',
44
+ padding: `3px ${themeSpacing.small}`,
45
+ backgroundColor: themeColors.primary,
46
+ border: 'none',
47
+ borderRadius: `var(--seekora-refinement-radius, 4px)`,
48
+ fontSize: '11px',
49
+ color: '#fff',
50
+ fontWeight: 600,
51
+ textTransform: 'uppercase',
52
+ letterSpacing: '0.5px',
53
+ };
54
+ case 'text-list':
55
+ return {
56
+ display: 'flex',
57
+ alignItems: 'center',
58
+ padding: `${themeSpacing.small} 0`,
59
+ backgroundColor: 'transparent',
60
+ border: 'none',
61
+ borderBottom: `1px solid ${baseBorder}`,
62
+ borderRadius: '0',
63
+ fontSize: '14px',
64
+ color: baseColor,
65
+ };
66
+ case 'chips':
67
+ default:
68
+ return {
69
+ display: 'inline-flex',
70
+ alignItems: 'center',
71
+ padding: `${themeSpacing.small} ${themeSpacing.medium}`,
72
+ backgroundColor: baseBg,
73
+ border: `1px solid ${baseBorder}`,
74
+ borderRadius: `var(--seekora-refinement-radius, ${typeof themeBorderRadius === 'string' ? themeBorderRadius : themeBorderRadius.medium})`,
75
+ fontSize: '13px',
76
+ color: baseColor,
77
+ };
78
+ }
79
+ };
80
+ /** Get variant-specific class name from theme */
81
+ const getVariantClass = (variant, refinementsTheme) => {
82
+ switch (variant) {
83
+ case 'tags': return refinementsTheme.tag;
84
+ case 'pills': return refinementsTheme.pill;
85
+ case 'badges': return refinementsTheme.badge;
86
+ case 'chips': return refinementsTheme.chip;
87
+ default: return refinementsTheme.item;
88
+ }
89
+ };
90
+ export const CurrentRefinements = ({ refinements: refinementsProp, onRefinementClear, onClearAll, renderRefinement, showClearAll = true, variant = 'chips', layout = 'horizontal', fieldColors, renderCloseIcon, className, style, theme: customTheme, }) => {
10
91
  const { theme } = useSearchContext();
92
+ const { refinements: stateRefinements, removeRefinement, clearRefinements } = useSearchState();
11
93
  const refinementsTheme = customTheme || {};
94
+ // Use props if provided, otherwise auto-read from StateManager
95
+ const refinements = refinementsProp !== undefined
96
+ ? refinementsProp
97
+ : stateRefinements.map(r => ({ field: r.field, value: r.value }));
98
+ // Track items for entry/exit animations
99
+ const [visibleItems, setVisibleItems] = useState(new Set());
100
+ const [exitingItems, setExitingItems] = useState(new Set());
101
+ const prevRefinementsRef = useRef([]);
102
+ useEffect(() => {
103
+ const currentKeys = new Set(refinements.map(r => `${r.field}:${r.value}`));
104
+ const prevKeys = new Set(prevRefinementsRef.current.map(r => `${r.field}:${r.value}`));
105
+ // Detect removed items for exit animation
106
+ const removed = new Set();
107
+ prevKeys.forEach(key => {
108
+ if (!currentKeys.has(key))
109
+ removed.add(key);
110
+ });
111
+ if (removed.size > 0) {
112
+ setExitingItems(removed);
113
+ // Remove after animation completes
114
+ setTimeout(() => setExitingItems(new Set()), 200);
115
+ }
116
+ // Mark new items for entry animation
117
+ setVisibleItems(currentKeys);
118
+ prevRefinementsRef.current = [...refinements];
119
+ }, [refinements]);
12
120
  const handleClear = (field, value) => {
121
+ // If synced with StateManager and no prop provided, auto-clear via StateManager
122
+ if (refinementsProp === undefined) {
123
+ removeRefinement(field, value);
124
+ }
13
125
  if (onRefinementClear) {
14
126
  onRefinementClear(field, value);
15
127
  }
16
128
  };
17
129
  const handleClearAll = () => {
130
+ // If synced with StateManager, auto-clear all via StateManager
131
+ if (refinementsProp === undefined) {
132
+ clearRefinements();
133
+ }
18
134
  if (onClearAll) {
19
135
  onClearAll();
20
136
  }
21
137
  };
22
- const defaultRenderRefinement = (refinement, index) => (React.createElement("div", { key: `${refinement.field}-${refinement.value}-${index}`, className: refinementsTheme.item, style: {
23
- display: 'inline-flex',
24
- alignItems: 'center',
25
- padding: `${theme.spacing.small} ${theme.spacing.medium}`,
26
- margin: `0 ${theme.spacing.small} ${theme.spacing.small} 0`,
27
- backgroundColor: theme.colors.hover,
28
- border: `1px solid ${theme.colors.border}`,
29
- borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
30
- fontSize: theme.typography.fontSize.small,
31
- } },
32
- React.createElement("span", { className: refinementsTheme.label, style: {
33
- marginRight: theme.spacing.small,
34
- color: theme.colors.text,
35
- fontWeight: '500',
138
+ const defaultCloseIcon = () => (React.createElement("span", { "aria-hidden": "true", style: { lineHeight: 1 } }, "\u00D7"));
139
+ const defaultRenderRefinement = (refinement, index) => {
140
+ const key = `${refinement.field}:${refinement.value}`;
141
+ const fieldColor = fieldColors?.[refinement.field];
142
+ const isEntering = visibleItems.has(key) && !prevRefinementsRef.current.some(r => `${r.field}:${r.value}` === key);
143
+ const variantStyles = getVariantStyles(variant, theme.colors, theme.spacing, theme.borderRadius, fieldColor);
144
+ const variantClass = getVariantClass(variant, refinementsTheme);
145
+ return (React.createElement("div", { key: `${key}-${index}`, className: clsx(refinementsTheme.item, variantClass), role: "listitem", style: {
146
+ ...variantStyles,
147
+ margin: layout === 'vertical'
148
+ ? `0 0 ${theme.spacing.small} 0`
149
+ : `0 ${theme.spacing.small} ${theme.spacing.small} 0`,
150
+ transition: 'all 200ms ease-in-out',
151
+ opacity: exitingItems.has(key) ? 0 : 1,
152
+ transform: exitingItems.has(key) ? 'scale(0.8)' : 'scale(1)',
153
+ animation: isEntering ? 'seekoraChipIn 200ms ease-out' : undefined,
36
154
  } },
37
- refinement.label || refinement.field,
38
- ":"),
39
- React.createElement("span", { className: refinementsTheme.value, style: {
40
- marginRight: theme.spacing.small,
41
- color: theme.colors.text,
42
- } }, refinement.displayValue || refinement.value),
43
- React.createElement("button", { type: "button", onClick: () => handleClear(refinement.field, refinement.value), className: refinementsTheme.clearButton, style: {
44
- border: 'none',
45
- backgroundColor: 'transparent',
46
- color: theme.colors.text,
47
- cursor: 'pointer',
48
- fontSize: theme.typography.fontSize.medium,
49
- padding: 0,
50
- marginLeft: theme.spacing.small,
51
- width: '20px',
52
- height: '20px',
53
- display: 'flex',
54
- alignItems: 'center',
55
- justifyContent: 'center',
56
- borderRadius: '50%',
57
- transition: theme.transitions?.fast || '150ms ease-in-out',
58
- }, "aria-label": `Clear ${refinement.label || refinement.field}: ${refinement.value}` }, "\u00D7")));
155
+ variant !== 'badges' && (React.createElement("span", { className: refinementsTheme.label, style: {
156
+ marginRight: theme.spacing.small,
157
+ fontWeight: '500',
158
+ opacity: 0.7,
159
+ } },
160
+ refinement.label || refinement.field,
161
+ ":")),
162
+ React.createElement("span", { className: refinementsTheme.value }, refinement.displayValue || refinement.value),
163
+ React.createElement("button", { type: "button", onClick: () => handleClear(refinement.field, refinement.value), className: refinementsTheme.clearButton, style: {
164
+ border: 'none',
165
+ backgroundColor: 'transparent',
166
+ color: 'inherit',
167
+ cursor: 'pointer',
168
+ fontSize: '14px',
169
+ padding: '0 0 0 6px',
170
+ display: 'flex',
171
+ alignItems: 'center',
172
+ justifyContent: 'center',
173
+ borderRadius: '50%',
174
+ transition: 'opacity 150ms ease-in-out',
175
+ opacity: 0.6,
176
+ }, "aria-label": `Clear ${refinement.label || refinement.field}: ${refinement.value}`, onMouseEnter: e => (e.currentTarget.style.opacity = '1'), onMouseLeave: e => (e.currentTarget.style.opacity = '0.6') }, renderCloseIcon ? renderCloseIcon() : defaultCloseIcon())));
177
+ };
59
178
  if (refinements.length === 0) {
60
179
  return null;
61
180
  }
62
- return (React.createElement("div", { className: clsx(refinementsTheme.container, className), style: style },
63
- React.createElement("div", { className: refinementsTheme.list, style: {
64
- display: 'flex',
65
- flexWrap: 'wrap',
66
- alignItems: 'center',
67
- marginBottom: showClearAll ? theme.spacing.medium : 0,
68
- } }, refinements.map((refinement, index) => {
181
+ // Group refinements by field for grouped layout
182
+ const groupedRefinements = layout === 'grouped'
183
+ ? refinements.reduce((acc, r) => {
184
+ if (!acc[r.field])
185
+ acc[r.field] = [];
186
+ acc[r.field].push(r);
187
+ return acc;
188
+ }, {})
189
+ : null;
190
+ const containerStyles = {
191
+ ...style,
192
+ };
193
+ const listStyles = {
194
+ display: 'flex',
195
+ flexWrap: layout === 'vertical' ? 'nowrap' : 'wrap',
196
+ flexDirection: layout === 'vertical' ? 'column' : 'row',
197
+ alignItems: layout === 'vertical' ? 'flex-start' : 'center',
198
+ marginBottom: showClearAll ? theme.spacing.medium : 0,
199
+ };
200
+ return (React.createElement("div", { className: clsx(refinementsTheme.container, className), style: containerStyles },
201
+ React.createElement("style", null, `
202
+ @keyframes seekoraChipIn {
203
+ from { opacity: 0; transform: scale(0.8); }
204
+ to { opacity: 1; transform: scale(1); }
205
+ }
206
+ `),
207
+ layout === 'grouped' && groupedRefinements ? (Object.entries(groupedRefinements).map(([field, items]) => (React.createElement("div", { key: field, className: refinementsTheme.group, style: { marginBottom: theme.spacing.medium } },
208
+ React.createElement("div", { className: refinementsTheme.groupLabel, style: {
209
+ fontSize: theme.typography.fontSize.small,
210
+ fontWeight: 600,
211
+ color: theme.colors.text,
212
+ marginBottom: theme.spacing.small,
213
+ textTransform: 'capitalize',
214
+ } }, items[0]?.label || field),
215
+ React.createElement("div", { role: "list", style: listStyles }, items.map((refinement, index) => {
216
+ return renderRefinement
217
+ ? renderRefinement(refinement, index)
218
+ : defaultRenderRefinement(refinement, index);
219
+ })))))) : (React.createElement("div", { role: "list", className: refinementsTheme.list, style: listStyles }, refinements.map((refinement, index) => {
69
220
  return renderRefinement
70
221
  ? renderRefinement(refinement, index)
71
222
  : defaultRenderRefinement(refinement, index);
72
- })),
223
+ }))),
73
224
  showClearAll && refinements.length > 1 && (React.createElement("button", { type: "button", onClick: handleClearAll, className: refinementsTheme.clearAllButton, style: {
74
225
  padding: `${theme.spacing.small} ${theme.spacing.medium}`,
75
226
  border: `1px solid ${theme.colors.border}`,
@@ -79,5 +230,6 @@ export const CurrentRefinements = ({ refinements = [], onRefinementClear, onClea
79
230
  cursor: 'pointer',
80
231
  fontSize: theme.typography.fontSize.small,
81
232
  textDecoration: 'underline',
233
+ transition: 'background-color 150ms ease-in-out',
82
234
  } }, "Clear all filters"))));
83
235
  };
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Facets Component
3
3
  *
4
- * Displays facet filters for search results
4
+ * Displays facet filters for search results with multiple display variants,
5
+ * client-side search, count badges, and color swatch support.
5
6
  */
6
7
  import React from 'react';
7
8
  import type { SearchResponse } from '@seekora-ai/search-sdk';
@@ -26,7 +27,23 @@ export interface FacetsTheme {
26
27
  facetItemCount?: string;
27
28
  facetItemLabel?: string;
28
29
  checkbox?: string;
30
+ /** Color swatch circle/square */
31
+ colorSwatch?: string;
32
+ /** Color swatch when selected */
33
+ colorSwatchSelected?: string;
34
+ /** Inner element of color swatch (for checkmark overlay) */
35
+ colorSwatchInner?: string;
36
+ /** Search input within a facet group */
37
+ searchInput?: string;
38
+ /** Collapsible header row */
39
+ collapsibleHeader?: string;
40
+ /** Chevron/expand icon in collapsible header */
41
+ collapsibleIcon?: string;
42
+ /** Count badge pill */
43
+ countBadge?: string;
29
44
  }
45
+ export type FacetVariant = 'checkbox' | 'color-swatch' | 'collapsible';
46
+ export type FacetSize = 'small' | 'medium' | 'large';
30
47
  export interface FacetsProps {
31
48
  /** Search results response */
32
49
  results?: SearchResponse | null;
@@ -48,6 +65,18 @@ export interface FacetsProps {
48
65
  style?: React.CSSProperties;
49
66
  /** Custom theme */
50
67
  theme?: FacetsTheme;
68
+ /** Display variant: checkbox (default), color-swatch, or collapsible */
69
+ variant?: FacetVariant;
70
+ /** When true, show a search input at the top of each facet group */
71
+ searchable?: boolean;
72
+ /** Show count badges (default: true) */
73
+ showCounts?: boolean;
74
+ /** Maps facet values to CSS colors (used by color-swatch variant) */
75
+ colorMap?: Record<string, string>;
76
+ /** For collapsible variant, whether facets start collapsed (default: false) */
77
+ defaultCollapsed?: boolean;
78
+ /** Size preset: small, medium (default), or large */
79
+ size?: FacetSize;
51
80
  }
52
81
  export declare const Facets: React.FC<FacetsProps>;
53
82
  //# sourceMappingURL=Facets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Facets.d.ts","sourceRoot":"","sources":["../../src/components/Facets.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,iDAAiD;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,uCAAuC;IACvC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC/D,4CAA4C;IAC5C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IACpF,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAmRxC,CAAC"}
1
+ {"version":3,"file":"Facets.d.ts","sourceRoot":"","sources":["../../src/components/Facets.tsx"],"names":[],"mappings":"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"}