@iqual/nuxt-icms 1.3.1 → 1.4.1

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 (122) hide show
  1. package/assets/symbols/chevron-right.svg +1 -1
  2. package/components/Blokkli/HeroImage/index.vue +1 -1
  3. package/components/Blokkli/Teasers/icon.svg +3 -3
  4. package/components/DesignSystem/Atoms/Button.vue +86 -36
  5. package/components/DesignSystem/Atoms/Caption.vue +10 -10
  6. package/components/DesignSystem/Atoms/Container.vue +10 -6
  7. package/components/DesignSystem/Atoms/GridRow.vue +4 -3
  8. package/components/DesignSystem/Atoms/LinkListItem.vue +31 -8
  9. package/components/DesignSystem/Molecules/ButtonGroup.vue +18 -3
  10. package/components/DesignSystem/Molecules/Card.vue +86 -31
  11. package/components/DesignSystem/Molecules/IconText.vue +37 -16
  12. package/components/DesignSystem/Molecules/MediaLightbox.vue +213 -58
  13. package/components/DesignSystem/Molecules/MediaSlider.vue +88 -25
  14. package/components/DesignSystem/Molecules/Partnership.vue +40 -9
  15. package/components/DesignSystem/Molecules/Table.vue +90 -25
  16. package/components/DesignSystem/Molecules/TitleComposition.vue +15 -12
  17. package/components/DesignSystem/Organisms/ContentBlock.vue +61 -15
  18. package/components/DesignSystem/Organisms/FacetedListing.vue +170 -0
  19. package/components/DesignSystem/Organisms/FlipTeaser.vue +119 -47
  20. package/components/DesignSystem/Organisms/HeaderHero.vue +167 -0
  21. package/components/DesignSystem/Organisms/HeaderTextImage.vue +71 -0
  22. package/components/DesignSystem/Organisms/LogoElement.vue +33 -10
  23. package/components/DesignSystem/Organisms/Map.vue +11 -6
  24. package/components/DesignSystem/Organisms/SearchResults.vue +41 -0
  25. package/components/DesignSystem/Organisms/TeamElement.vue +84 -20
  26. package/components/DesignSystem/Organisms/TeaserCard.vue +87 -34
  27. package/components/DesignSystem/Organisms/Testimonial.vue +82 -12
  28. package/components/DesignSystem/Organisms/TimelineElement.vue +42 -12
  29. package/components/DesignSystem/Organisms/TwoColumnTextElement.vue +44 -9
  30. package/components/DesignSystem/Pages/Search.vue +39 -0
  31. package/components/Drupal/Breadcrumb/index.vue +16 -5
  32. package/components/Drupal/Messages/index.vue +16 -5
  33. package/components/Drupal/Webform/fragment.graphql +8 -5
  34. package/components/Drupal/Webform/index.vue +20 -9
  35. package/components/Drupal/Webform/query.graphql +18 -16
  36. package/components/Form/CheckboxInput.vue +6 -6
  37. package/components/Form/CheckboxInputs.vue +5 -5
  38. package/components/Form/FileUploadInput.vue +6 -6
  39. package/components/Form/RadioButtonsInput.vue +5 -5
  40. package/components/Form/SelectInput.vue +7 -7
  41. package/components/Form/SubmitButton.vue +1 -1
  42. package/components/Form/TextAreaInput.vue +2 -2
  43. package/components/Form/TextEmailInput.vue +2 -2
  44. package/components/Form/TextInput.vue +2 -2
  45. package/components/Form/TextPhoneInput.vue +2 -2
  46. package/components/Form/composables/useFormElement.ts +5 -5
  47. package/components/Form/utils/types.ts +8 -7
  48. package/components/Media/Icon/index.vue +10 -6
  49. package/components/Media/Image/index.vue +26 -20
  50. package/components/Media/RemoteVideo/index.vue +34 -21
  51. package/components/Media/Video/index.vue +6 -5
  52. package/components/Node/Icms/Page/Teaser/index.vue +6 -4
  53. package/components/Node/Icms/Page/index.vue +2 -2
  54. package/components/Paragraph/Button/Element/index.vue +9 -2
  55. package/components/Paragraph/CallToAction/index.vue +43 -10
  56. package/components/Paragraph/Card/Element/index.vue +2 -1
  57. package/components/Paragraph/Card/Layout/index.vue +29 -10
  58. package/components/Paragraph/Contact/index.vue +41 -12
  59. package/components/Paragraph/Downloads/index.vue +82 -33
  60. package/components/Paragraph/FAQ/Element/index.vue +41 -12
  61. package/components/Paragraph/FAQ/Layout/index.vue +47 -13
  62. package/components/Paragraph/FlipTeasers/index.vue +26 -6
  63. package/components/Paragraph/Gallery/index.vue +42 -10
  64. package/components/Paragraph/HeroImage/index.vue +62 -16
  65. package/components/Paragraph/IconText/Element/index.vue +7 -1
  66. package/components/Paragraph/IconText/Layout/index.vue +39 -12
  67. package/components/Paragraph/Introduction/index.vue +50 -15
  68. package/components/Paragraph/Logo/Element/fragment.graphql +1 -0
  69. package/components/Paragraph/Logo/Element/index.vue +7 -2
  70. package/components/Paragraph/Media/index.vue +32 -31
  71. package/components/Paragraph/Partnerships/Element/fragment.graphql +1 -0
  72. package/components/Paragraph/Partnerships/Element/index.vue +7 -0
  73. package/components/Paragraph/Partnerships/Layout/index.vue +100 -27
  74. package/components/Paragraph/SingleTestimonial/index.vue +58 -15
  75. package/components/Paragraph/Table/index.vue +32 -9
  76. package/components/Paragraph/Tabs/Element/index.vue +44 -10
  77. package/components/Paragraph/Tabs/Layout/index.vue +123 -37
  78. package/components/Paragraph/Team/Element/index.vue +18 -1
  79. package/components/Paragraph/Team/Layout/index.vue +30 -7
  80. package/components/Paragraph/Teasers/index.vue +33 -7
  81. package/components/Paragraph/Testimonial/Element/index.vue +30 -5
  82. package/components/Paragraph/Testimonial/Layout/index.vue +78 -24
  83. package/components/Paragraph/Text/index.vue +32 -10
  84. package/components/Paragraph/TextMedia/index.vue +44 -13
  85. package/components/Paragraph/Timeline/Element/index.vue +23 -7
  86. package/components/Paragraph/Timeline/Layout/index.vue +232 -67
  87. package/components/Paragraph/TwoColumnText/Element/index.vue +20 -3
  88. package/components/Paragraph/TwoColumnText/Layout/index.vue +8 -1
  89. package/components/Paragraph/iFrame/index.vue +31 -11
  90. package/components/Search/Facets/FacetDropdownUI.vue +351 -77
  91. package/components/Search/Facets/FacetedSearchUI.vue +257 -101
  92. package/components/Search/Facets/fragment.graphql +5 -1
  93. package/components/Search/Input/index.vue +78 -20
  94. package/components/Section/Footer/index.vue +170 -30
  95. package/components/Section/Header/Buttons.vue +34 -0
  96. package/components/Section/Header/DesktopMainMenu.vue +160 -0
  97. package/components/Section/Header/DesktopMainMenuDropdown.vue +170 -0
  98. package/components/Section/Header/LanguageDropdown.vue +95 -64
  99. package/components/Section/Header/LanguageLinks.vue +39 -0
  100. package/components/Section/Header/Logo.vue +24 -0
  101. package/components/Section/Header/MainButtons.vue +31 -0
  102. package/components/Section/Header/MenuIcon.vue +61 -49
  103. package/components/Section/Header/MetaButtons.vue +31 -0
  104. package/components/Section/Header/MetaMenu.vue +55 -53
  105. package/components/Section/Header/MobileMainMenu.vue +23 -0
  106. package/components/Section/Header/MobileMainMenuItem.vue +191 -0
  107. package/components/Section/Header/index.vue +183 -185
  108. package/composables/useMenu.ts +2 -2
  109. package/composables/useMobileMenuOverlayBus.ts +44 -0
  110. package/composables/useNavigationOffset.ts +2 -2
  111. package/composables/useTheme.ts +75 -0
  112. package/formkit.theme.ts +541 -586
  113. package/layouts/default.vue +7 -35
  114. package/layouts/error.vue +7 -32
  115. package/nuxt.config.ts +13 -0
  116. package/package.json +1 -1
  117. package/plugins/initData.ts +8 -5
  118. package/queries/query.initData.graphql +4 -2
  119. package/tailwind.config.ts +11 -11
  120. package/types/global.ts +1 -0
  121. package/components/Section/Header/GlobalMenu.vue +0 -335
  122. package/components/Section/Header/LanguageSwitcher.vue +0 -37
@@ -7,12 +7,19 @@
7
7
  v-model="facetSelections"
8
8
  @facets-change="onFacetsChange"
9
9
  :total-count="totalCount"
10
- :displayed-count="props.groupResultsByFacet ?
11
- displayedResults?.reduce((total, group) => total + (group?.results?.length || 0), 0) :
12
- displayedResults?.[0]?.results?.length"
10
+ :displayed-count="
11
+ props.groupResultsByFacet
12
+ ? displayedResults?.reduce(
13
+ (total, group) => total + (group?.results?.length || 0),
14
+ 0,
15
+ )
16
+ : displayedResults?.[0]?.results?.length
17
+ "
13
18
  :loading="isLoading"
14
19
  :colorScheme="colorScheme"
15
- class="mb-6"
20
+ :class="
21
+ themedClass('listingTypeAllSearchFacetsFacetDropdownUIClass', 'mb-6')
22
+ "
16
23
  :enable-text-search="enableTextSearch"
17
24
  :search-term="searchTerm"
18
25
  @update:search-term="onSearchTermChange"
@@ -26,7 +33,7 @@
26
33
  >{{ JSON.stringify(facetSelections, null, 2) }}</pre
27
34
  >
28
35
  <pre
29
- class="bg-blue-50 mt-2 whitespace-pre rounded p-3 text-xs"
36
+ class="mt-2 whitespace-pre rounded bg-blue-50 p-3 text-xs"
30
37
  v-if="facetData.length"
31
38
  >
32
39
  Facets: {{ facetData.length }} items</pre
@@ -36,43 +43,92 @@ Facets: {{ facetData.length }} items</pre
36
43
 
37
44
  <template v-if="debug && listingType !== 'all'">
38
45
  <!-- Debug info for manual/contextual filters -->
39
- <pre class="bg-yellow-50 mb-4 whitespace-pre rounded p-3 text-xs">
40
- Active Filters ({{ listingType }}): {{
46
+ <pre class="mb-4 whitespace-pre rounded bg-yellow-50 p-3 text-xs">
47
+ Active Filters ({{ listingType }}): {{
41
48
  JSON.stringify(activeFilters, null, 2)
42
49
  }}</pre
43
50
  >
44
51
  </template>
52
+
45
53
  <!-- Results Section -->
46
- <div class="results-container">
54
+ <div :class="themedClass('resultsContainerClass')">
47
55
  <template v-if="displayedResults?.length">
48
56
  <div
49
57
  v-for="(group, groupIndex) in displayedResults"
50
58
  :key="`group-${groupIndex}`"
59
+ :class="themedClass('resultGroupClass')"
51
60
  >
52
61
  <slot name="results" :results="group" :loading="loadingMore">
53
- <p v-if="props.groupResultsByFacet && 'label' in group && group?.label">{{ group?.label }} <span v-if="'count' in group && group?.count">({{ group?.count }})</span></p>
62
+ <p
63
+ v-if="
64
+ props.groupResultsByFacet && 'label' in group && group?.label
65
+ "
66
+ :class="themedClass('resultGroupLabelClass')"
67
+ >
68
+ {{ group?.label }}
69
+ <span
70
+ v-if="'count' in group && group?.count"
71
+ :class="themedClass('resultGroupCountClass')"
72
+ >
73
+ ({{ group?.count }})
74
+ </span>
75
+ </p>
54
76
  <!-- Default slot content if no slot is provided -->
55
77
  <div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
56
- <div v-for="(result, index) in group?.results"
78
+ <div
79
+ v-for="(result, index) in group?.results"
57
80
  :key="`result-${index}`"
58
81
  >
59
- <pre class="rounded bg-gray-100 p-2 text-xs overflow-hidden">{{
60
- JSON.stringify(result, null, 2)
61
- }}</pre>
82
+ <pre class="overflow-hidden rounded bg-gray-100 p-2 text-xs">
83
+ {{ JSON.stringify(result, null, 2) }}
84
+ </pre>
62
85
  </div>
63
86
  </div>
64
87
  </slot>
65
-
88
+
66
89
  <!-- Group-specific Load More Section (for grouped results) -->
67
- <div v-if="props.groupResultsByFacet && 'label' in group && canGroupLoadMore(group)" class="mt-6 flex justify-center">
68
- <slot name="group-load-more" :loadMore="() => loadMoreGroup(group)" :loading="isGroupLoading(group)" :group="group">
90
+ <div
91
+ v-if="
92
+ props.groupResultsByFacet &&
93
+ 'label' in group &&
94
+ canGroupLoadMore(group)
95
+ "
96
+ :class="
97
+ themedClass(
98
+ 'groupLoadMoreButtonContainerClass',
99
+ 'mt-6 flex justify-center',
100
+ )
101
+ "
102
+ >
103
+ <slot
104
+ name="group-load-more"
105
+ :loadMore="() => loadMoreGroup(group)"
106
+ :loading="isGroupLoading(group)"
107
+ :group="group"
108
+ >
69
109
  <button
70
110
  @click="loadMoreGroup(group)"
71
111
  :disabled="isGroupLoading(group)"
72
- :class="props.loadMoreButtonClass || defaultButtonClass"
112
+ :class="
113
+ cn(
114
+ button({ colorScheme }),
115
+ themedClass('groupLoadMoreButtonClass'),
116
+ props.loadMoreButtonClass,
117
+ )
118
+ "
73
119
  >
74
- <span v-if="!isGroupLoading(group)">{{ defaultLoadMoreText }}</span>
75
- <span v-else>{{ defaultLoadingText }}</span>
120
+ <span
121
+ v-if="!isGroupLoading(group)"
122
+ :class="themedClass('groupLoadMoreButtonLabelClass')"
123
+ >
124
+ {{ defaultLoadMoreText }}
125
+ </span>
126
+ <span
127
+ v-else
128
+ :class="themedClass('groupLoadMoreLoadingButtonLabelClass')"
129
+ >
130
+ {{ defaultLoadingText }}
131
+ </span>
76
132
  </button>
77
133
  </slot>
78
134
  </div>
@@ -81,7 +137,14 @@ Active Filters ({{ listingType }}): {{
81
137
 
82
138
  <template v-else-if="!isLoading">
83
139
  <slot name="no-results">
84
- <div class="col-span-12 py-8 text-center text-gray-500">
140
+ <div
141
+ :class="
142
+ themedClass(
143
+ 'noResultsContainerClass',
144
+ 'col-span-12 py-8 text-center text-gray-500',
145
+ )
146
+ "
147
+ >
85
148
  {{ defaultNoResultsText }}
86
149
  </div>
87
150
  </slot>
@@ -89,23 +152,47 @@ Active Filters ({{ listingType }}): {{
89
152
 
90
153
  <template v-if="isLoading">
91
154
  <slot name="loading">
92
- <div class="col-span-12 py-8 text-center text-gray-500">
93
- {{ defaultLoadingText }}
155
+ <div
156
+ :class="
157
+ themedClass(
158
+ 'loadingContainerClass',
159
+ 'col-span-12 py-8 text-center',
160
+ )
161
+ "
162
+ >
163
+ <span :class="loadingText({ colorScheme })">
164
+ {{ defaultLoadingText }}
165
+ </span>
94
166
  </div>
95
167
  </slot>
96
168
  </template>
97
169
  </div>
98
170
 
99
171
  <!-- Global Load More Section (for non-grouped results) -->
100
- <div v-if="showLoadMore" class="mt-10 flex justify-center lg:mt-20">
172
+ <div
173
+ v-if="showLoadMore"
174
+ :class="
175
+ themedClass(
176
+ 'globalLoadMoreButtonContainer',
177
+ 'mt-10 flex justify-center lg:mt-20',
178
+ )
179
+ "
180
+ >
101
181
  <slot name="load-more" :loadMore="loadMore" :loading="loadingMore">
102
182
  <button
103
183
  @click="loadMore"
104
184
  :disabled="loadingMore"
105
- :class="props.loadMoreButtonClass || defaultButtonClass"
185
+ :class="cn(button({ colorScheme }), loadMoreButtonClass)"
106
186
  >
107
- <span v-if="!loadingMore">{{ defaultLoadMoreText }}</span>
108
- <span v-else>{{ defaultLoadingText }}</span>
187
+ <span
188
+ v-if="!loadingMore"
189
+ :class="themedClass('globalLoadMoreButtonLabel')"
190
+ >
191
+ {{ defaultLoadMoreText }}
192
+ </span>
193
+ <span v-else :class="themedClass('globalLoadMoreLoadingButtonLabel')">
194
+ {{ defaultLoadingText }}
195
+ </span>
109
196
  </button>
110
197
  </slot>
111
198
  </div>
@@ -114,7 +201,11 @@ Active Filters ({{ listingType }}): {{
114
201
 
115
202
  <script lang="ts" setup>
116
203
  import { nextTick } from 'vue'
204
+ import type { ColorScheme } from '@iqual/nuxt-icms/types/global'
117
205
  import type { SearchApiQueryFilterInput } from '#graphql-operations'
206
+ import { useTheme } from '@iqual/nuxt-icms/composables/useTheme'
207
+ import { tv } from 'tailwind-variants'
208
+ import cn from '@iqual/nuxt-icms/composables/useCn'
118
209
 
119
210
  export interface FacetFilterItem {
120
211
  id: string
@@ -156,7 +247,7 @@ export interface FacetedSearchUIProps {
156
247
  debug?: boolean
157
248
 
158
249
  /** Color scheme for default button styling */
159
- colorScheme?: 'none' | 'dark' | 'light' | 'accent'
250
+ colorScheme?: ColorScheme
160
251
 
161
252
  /** Custom CSS classes for the load more button */
162
253
  loadMoreButtonClass?: string
@@ -179,6 +270,8 @@ const props = withDefaults(defineProps<FacetedSearchUIProps>(), {
179
270
  conjunction: 'AND',
180
271
  })
181
272
 
273
+ const themedClass = useTheme('SearchFacetsFacetedSearchUI')
274
+
182
275
  // Get the $texts function for internationalization
183
276
  const { $texts } = useNuxtApp()
184
277
 
@@ -280,9 +373,9 @@ const buildSearchFilter = (
280
373
  return { conditions: baseConditions }
281
374
  } else if (baseConditions.length === 0) {
282
375
  // If no base conditions, return additional conditions with conjunction
283
- return {
376
+ return {
284
377
  conditions: additionalConditions,
285
- conjunction: props.conjunction
378
+ conjunction: props.conjunction,
286
379
  }
287
380
  } else {
288
381
  // Create the exact structure: base group AND additional group (with specified conjunction)
@@ -290,13 +383,13 @@ const buildSearchFilter = (
290
383
  conjunction: 'AND',
291
384
  groups: [
292
385
  {
293
- conditions: baseConditions
386
+ conditions: baseConditions,
294
387
  },
295
388
  {
296
389
  conditions: additionalConditions,
297
- conjunction: props.conjunction
298
- }
299
- ]
390
+ conjunction: props.conjunction,
391
+ },
392
+ ],
300
393
  }
301
394
  }
302
395
  }
@@ -326,34 +419,44 @@ const { data: initialResultsData, refresh: refreshResults } =
326
419
  `facetedSearch-results-${props.listingType}-${JSON.stringify(props.baseFilter)}-${JSON.stringify(activeFilters.value)}`,
327
420
  async () => {
328
421
  const filter = buildSearchFilter()
329
-
422
+
330
423
  // Debug: Log the initial filter structure
331
424
  if (props.debug) {
332
- console.log('FacetedSearch - Initial filter being sent:', JSON.stringify(filter, null, 2))
425
+ console.log(
426
+ 'FacetedSearch - Initial filter being sent:',
427
+ JSON.stringify(filter, null, 2),
428
+ )
333
429
  }
334
-
430
+
335
431
  const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
336
432
  filter,
337
433
  facets: props.facets,
338
- limit: props?.groupResultsByFacet ? props.itemsPerPage * 10 : props.itemsPerPage,
434
+ limit: props?.groupResultsByFacet
435
+ ? props.itemsPerPage * 10
436
+ : props.itemsPerPage,
339
437
  offset: 0,
340
438
  keys: searchTerm.value ?? '',
341
439
  })
342
440
  isLoading.value = false
343
- if (props?.groupResultsByFacet && response?.data?.searchApiQuery?.facets) {
344
- response.data.searchApiQuery.facets = response.data?.searchApiQuery?.facets?.map(f => {return {
345
- count: f?.count,
346
- field: f?.field,
347
- label: f?.label,
348
- filter: f?.filter,
349
- results: f?.results?.slice(0, 4)
350
- }})
441
+ if (
442
+ props?.groupResultsByFacet &&
443
+ response?.data?.searchApiQuery?.facets
444
+ ) {
445
+ response.data.searchApiQuery.facets =
446
+ response.data?.searchApiQuery?.facets?.map((f) => {
447
+ return {
448
+ count: f?.count,
449
+ field: f?.field,
450
+ label: f?.label,
451
+ filter: f?.filter,
452
+ results: f?.results?.slice(0, 4),
453
+ }
454
+ })
351
455
  }
352
456
  return response.data?.searchApiQuery ?? null
353
457
  },
354
458
  )
355
459
 
356
-
357
460
  // Initialize facets from initial query (only for 'all' listing type)
358
461
  if (initialFacetsData.value) {
359
462
  allFacets.value = initialFacetsData.value.facets || []
@@ -368,22 +471,27 @@ async function updateSearchResults(selections: Record<string, string[]>) {
368
471
  try {
369
472
  isLoading.value = true
370
473
  currentPage.value = 1 // Reset pagination when filters change
371
-
474
+
372
475
  // Reset group pagination states when filters change
373
476
  groupPagination.value = {}
374
477
  groupLoadingMore.value = {}
375
-
478
+
376
479
  const filter = buildSearchFilter(selections)
377
480
 
378
481
  // Debug: Log the filter structure
379
482
  if (props.debug) {
380
- console.log('FacetedSearch - Filter being sent:', JSON.stringify(filter, null, 2))
483
+ console.log(
484
+ 'FacetedSearch - Filter being sent:',
485
+ JSON.stringify(filter, null, 2),
486
+ )
381
487
  }
382
488
 
383
489
  const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
384
490
  filter,
385
491
  facets: props.facets,
386
- limit: props?.groupResultsByFacet ? props.itemsPerPage * 10 : props.itemsPerPage,
492
+ limit: props?.groupResultsByFacet
493
+ ? props.itemsPerPage * 10
494
+ : props.itemsPerPage,
387
495
  offset: 0,
388
496
  keys: searchTerm.value ?? '',
389
497
  })
@@ -393,29 +501,27 @@ async function updateSearchResults(selections: Record<string, string[]>) {
393
501
  // Apply the same transformation as in the initial query
394
502
  let processedFacets = response?.data?.searchApiQuery?.facets
395
503
  if (processedFacets) {
396
- processedFacets = processedFacets.map(f => ({
504
+ processedFacets = processedFacets.map((f) => ({
397
505
  count: f?.count,
398
506
  field: f?.field,
399
507
  label: f?.label,
400
508
  filter: f?.filter,
401
- results: f?.results?.slice(0, 4)
509
+ results: f?.results?.slice(0, 4),
402
510
  }))
403
511
  }
404
-
512
+
405
513
  initialResultsData.value = {
406
514
  ...initialResultsData.value,
407
515
  facets: processedFacets,
408
516
  count: response?.data?.searchApiQuery?.count,
409
517
  }
410
- }
411
- else {
518
+ } else {
412
519
  initialResultsData.value = {
413
520
  ...initialResultsData.value,
414
521
  results: response?.data?.searchApiQuery?.results,
415
522
  count: response?.data?.searchApiQuery?.count,
416
523
  }
417
524
  }
418
-
419
525
  } catch (error) {
420
526
  console.error('Error updating search results:', error)
421
527
  } finally {
@@ -426,19 +532,23 @@ async function updateSearchResults(selections: Record<string, string[]>) {
426
532
  // Computed properties
427
533
  const displayedResults = computed(() => {
428
534
  if (props?.groupResultsByFacet) {
429
- return initialResultsData.value?.facets?.filter((facet) => {
430
- return facet?.field == props?.groupResultsByFacet
431
- }).map((facet) => {
432
- return {
433
- 'label': facet?.filter?.label,
434
- 'count': facet?.count,
435
- 'results': facet?.results || [],
436
- }
437
- })
535
+ return initialResultsData.value?.facets
536
+ ?.filter((facet) => {
537
+ return facet?.field == props?.groupResultsByFacet
538
+ })
539
+ .map((facet) => {
540
+ return {
541
+ label: facet?.filter?.label,
542
+ count: facet?.count,
543
+ results: facet?.results || [],
544
+ }
545
+ })
438
546
  }
439
- return [{
440
- 'results': initialResultsData.value?.results || []
441
- }]
547
+ return [
548
+ {
549
+ results: initialResultsData.value?.results || [],
550
+ },
551
+ ]
442
552
  })
443
553
 
444
554
  const totalCount = computed(() => {
@@ -525,24 +635,9 @@ watch(
525
635
  refreshResults()
526
636
  }
527
637
  },
528
- { immediate: false }
638
+ { immediate: false },
529
639
  )
530
640
 
531
- // Default button styling based on color scheme
532
- const defaultButtonClass = computed(() => {
533
- const baseClasses =
534
- 'shadow-none h-auto block text-h7 font-medium py-3 px-20 rounded-full duration-300 ease-in-out w-full md:w-fit border disabled:opacity-50 disabled:cursor-not-allowed'
535
-
536
- const colorSchemeClasses = {
537
- none: 'bg-white text-black hover:bg-black hover:text-white border-black',
538
- dark: 'bg-white text-black hover:bg-black hover:text-white border-black',
539
- light: 'bg-gray-50 text-black hover:bg-black hover:text-white border-black',
540
- accent: 'bg-white text-black hover:bg-black hover:text-white border-black',
541
- }
542
-
543
- return `${baseClasses} ${colorSchemeClasses[props.colorScheme] || colorSchemeClasses.none}`
544
- })
545
-
546
641
  // Load more handler
547
642
  async function loadMore() {
548
643
  if (loadingMore.value || isLoading.value) return
@@ -585,16 +680,19 @@ async function loadMore() {
585
680
  // Load more handler for specific group
586
681
  async function loadMoreGroup(group: any) {
587
682
  if (!props.groupResultsByFacet || !group || !('label' in group)) return
588
-
683
+
589
684
  const groupKey = getGroupKey(group)
590
685
  if (groupLoadingMore.value[groupKey] || isLoading.value) return
591
-
686
+
592
687
  groupLoadingMore.value[groupKey] = true
593
688
 
594
689
  try {
595
690
  // Find the facet filter value that corresponds to this group
596
- const groupFacetValue = initialResultsData.value?.facets?.find(f =>
597
- f && f.field === props.groupResultsByFacet && f.filter?.label === group.label
691
+ const groupFacetValue = initialResultsData.value?.facets?.find(
692
+ (f) =>
693
+ f &&
694
+ f.field === props.groupResultsByFacet &&
695
+ f.filter?.label === group.label,
598
696
  )?.filter?.id
599
697
 
600
698
  if (!groupFacetValue) {
@@ -610,28 +708,31 @@ async function loadMoreGroup(group: any) {
610
708
  // Step 1: First apply the facet filter and wait for it to complete
611
709
  const updatedSelections = {
612
710
  ...facetSelections.value,
613
- [props.groupResultsByFacet]: [groupFacetValue]
711
+ [props.groupResultsByFacet]: [groupFacetValue],
614
712
  }
615
-
713
+
616
714
  // Update facetSelections and trigger the normal facet change flow
617
715
  facetSelections.value = updatedSelections
618
716
  onFacetsChange(updatedSelections)
619
-
717
+
620
718
  // Wait for the facet change to complete
621
719
  await nextTick()
622
720
  // Wait a bit more to ensure the search results have been updated
623
- await new Promise(resolve => setTimeout(resolve, 100))
721
+ await new Promise((resolve) => setTimeout(resolve, 100))
624
722
  }
625
723
 
626
724
  // Step 2: Now do the load more operation
627
725
  // For grouped results, find the current results for this specific group
628
- const currentGroupData = initialResultsData.value?.facets?.find(f =>
629
- f && f.field === props.groupResultsByFacet && f.filter?.label === group.label
726
+ const currentGroupData = initialResultsData.value?.facets?.find(
727
+ (f) =>
728
+ f &&
729
+ f.field === props.groupResultsByFacet &&
730
+ f.filter?.label === group.label,
630
731
  )
631
-
732
+
632
733
  const currentGroupResults = currentGroupData?.results || []
633
734
  const currentCount = currentGroupResults.length
634
-
735
+
635
736
  // Use the current group result count as offset to load more
636
737
  const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
637
738
  filter: buildSearchFilter(facetSelections.value),
@@ -643,19 +744,23 @@ async function loadMoreGroup(group: any) {
643
744
  if (response.data?.searchApiQuery?.results) {
644
745
  // Append new results to the existing group results
645
746
  const newResults = response.data.searchApiQuery.results
646
-
747
+
647
748
  // Update the specific group's results in the facets array
648
749
  if (initialResultsData.value?.facets && currentGroupData) {
649
- const updatedFacets = initialResultsData.value.facets.map(facet => {
650
- if (facet && facet.field === props.groupResultsByFacet && facet.filter?.label === group.label) {
750
+ const updatedFacets = initialResultsData.value.facets.map((facet) => {
751
+ if (
752
+ facet &&
753
+ facet.field === props.groupResultsByFacet &&
754
+ facet.filter?.label === group.label
755
+ ) {
651
756
  return {
652
757
  ...facet,
653
- results: [...currentGroupResults, ...newResults]
758
+ results: [...currentGroupResults, ...newResults],
654
759
  }
655
760
  }
656
761
  return facet
657
762
  })
658
-
763
+
659
764
  initialResultsData.value = {
660
765
  ...initialResultsData.value,
661
766
  facets: updatedFacets,
@@ -676,6 +781,57 @@ async function loadMoreGroup(group: any) {
676
781
  }
677
782
  }
678
783
 
784
+ const button = tv({
785
+ base: themedClass(
786
+ 'buttonBase',
787
+ 'shadow-none h-auto block text-h7 font-medium py-3 px-20 rounded-full duration-300 ease-in-out w-full md:w-fit border disabled:opacity-50 disabled:cursor-not-allowed',
788
+ ),
789
+ variants: {
790
+ colorScheme: {
791
+ none: themedClass(
792
+ 'buttonVariantsColorSchemeNone',
793
+ 'bg-white text-black hover:bg-black hover:text-white border-black',
794
+ ),
795
+ dark: themedClass(
796
+ 'buttonVariantsColorSchemeDark',
797
+ 'bg-white text-black hover:bg-black hover:text-white border-black',
798
+ ),
799
+ light: themedClass(
800
+ 'buttonVariantsColorSchemeLight',
801
+ 'bg-gray-50 text-black hover:bg-black hover:text-white border-black',
802
+ ),
803
+ accent: themedClass(
804
+ 'buttonVariantsColorSchemeAccent',
805
+ 'bg-white text-black hover:bg-black hover:text-white border-black',
806
+ ),
807
+ },
808
+ },
809
+ defaultVariants: {
810
+ colorScheme: 'none',
811
+ },
812
+ })
813
+
814
+ const loadingText = tv({
815
+ base: themedClass('loadingTextBase'),
816
+ variants: {
817
+ colorScheme: {
818
+ none: themedClass('loadingTextVariantsColorSchemeNone', 'text-gray-500'),
819
+ dark: themedClass('loadingTextVariantsColorSchemeDark', 'text-gray-500'),
820
+ light: themedClass(
821
+ 'loadingTextVariantsColorSchemeLight',
822
+ 'text-gray-500',
823
+ ),
824
+ accent: themedClass(
825
+ 'loadingTextVariantsColorSchemeAccent',
826
+ 'text-gray-500',
827
+ ),
828
+ },
829
+ },
830
+ defaultVariants: {
831
+ colorScheme: 'none',
832
+ },
833
+ })
834
+
679
835
  // Debug logging
680
836
  watchEffect(() => {
681
837
  if (props.debug) {
@@ -32,10 +32,14 @@ query layoutOverviewResultsSearch(
32
32
  searchApiQuery(
33
33
  indexId: "content_search",
34
34
  filter: $filter
35
- facets: $facets,
35
+ facets: $facets
36
36
  limit: $limit
37
37
  offset: $offset
38
38
  keys: $keys
39
+ sort: [
40
+ {field: "weight", direction:DESC},
41
+ {field: "created", direction:DESC}
42
+ ]
39
43
  ) {
40
44
  count
41
45
  results {