@classic-homes/theme-svelte 1.42.3 → 1.43.0

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.
@@ -47,6 +47,12 @@
47
47
  onSearch?: (query: string) => void;
48
48
  /** Debounce delay in ms for search callback (default: 300) */
49
49
  debounceMs?: number;
50
+ /**
51
+ * Selected tags shown before the rest fold into a "+N more" toggle
52
+ * (default 6), so a long selection (e.g. a select-all) doesn't push the
53
+ * layout down. `Infinity` always shows every tag.
54
+ */
55
+ maxVisibleTags?: number;
50
56
  /** Additional class for the trigger */
51
57
  class?: string;
52
58
  }
@@ -68,6 +74,7 @@
68
74
  loading = false,
69
75
  onSearch,
70
76
  debounceMs = 300,
77
+ maxVisibleTags = 6,
71
78
  class: className,
72
79
  }: Props = $props();
73
80
 
@@ -85,11 +92,23 @@
85
92
  let debounceTimer: ReturnType<typeof setTimeout> | null = null;
86
93
  let open = $state(false);
87
94
 
88
- // Get labels for selected values
89
- const selectedLabels = $derived(
90
- value.map((v) => options.find((opt) => opt.value === v)?.label).filter(Boolean) as string[]
95
+ // The selected values that have an option, with their labels (tag order = pick order)
96
+ const selectedTags = $derived(
97
+ value.flatMap((v) => {
98
+ const label = options.find((opt) => opt.value === v)?.label;
99
+ return label ? [{ value: v, label }] : [];
100
+ })
91
101
  );
92
102
 
103
+ // Past maxVisibleTags the rest fold behind a "+N more" toggle.
104
+ let tagsExpanded = $state(false);
105
+ const tagLimit = $derived(Math.max(0, maxVisibleTags));
106
+ const hiddenTagCount = $derived(Math.max(0, selectedTags.length - tagLimit));
107
+ const visibleTags = $derived(
108
+ tagsExpanded || hiddenTagCount === 0 ? selectedTags : selectedTags.slice(0, tagLimit)
109
+ );
110
+ const tagsId = $derived(`${componentId}-tags`);
111
+
93
112
  // Always filter options locally based on search query
94
113
  const filteredOptions = $derived.by(() => {
95
114
  if (!searchQuery) return options;
@@ -203,10 +222,11 @@
203
222
 
204
223
  <div class={cn('w-full', className)}>
205
224
  <!-- Selected tags -->
206
- {#if selectedLabels.length > 0}
207
- <div class="flex flex-wrap gap-1 mb-2">
208
- {#each value as selectedValue}
209
- {@const labelText = options.find((o) => o.value === selectedValue)?.label}
225
+ {#if selectedTags.length > 0}
226
+ <div id={tagsId} class="flex flex-wrap gap-1 mb-2">
227
+ {#each visibleTags as tag (tag.value)}
228
+ {@const selectedValue = tag.value}
229
+ {@const labelText = tag.label}
210
230
  {#if labelText}
211
231
  <span
212
232
  class="inline-flex items-center gap-1 rounded-md bg-muted px-2 py-1 text-xs font-medium text-foreground"
@@ -237,6 +257,17 @@
237
257
  </span>
238
258
  {/if}
239
259
  {/each}
260
+ {#if hiddenTagCount > 0}
261
+ <button
262
+ type="button"
263
+ onclick={() => (tagsExpanded = !tagsExpanded)}
264
+ class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-primary underline-offset-2 hover:underline focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
265
+ aria-expanded={tagsExpanded}
266
+ aria-controls={tagsId}
267
+ >
268
+ {tagsExpanded ? 'Show less' : `+${hiddenTagCount} more`}
269
+ </button>
270
+ {/if}
240
271
  </div>
241
272
  {/if}
242
273
 
@@ -36,6 +36,12 @@ interface Props {
36
36
  onSearch?: (query: string) => void;
37
37
  /** Debounce delay in ms for search callback (default: 300) */
38
38
  debounceMs?: number;
39
+ /**
40
+ * Selected tags shown before the rest fold into a "+N more" toggle
41
+ * (default 6), so a long selection (e.g. a select-all) doesn't push the
42
+ * layout down. `Infinity` always shows every tag.
43
+ */
44
+ maxVisibleTags?: number;
39
45
  /** Additional class for the trigger */
40
46
  class?: string;
41
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classic-homes/theme-svelte",
3
- "version": "1.42.3",
3
+ "version": "1.43.0",
4
4
  "description": "Svelte components for the Classic theme system",
5
5
  "type": "module",
6
6
  "svelte": "./dist/lib/index.js",