@makolabs/ripple 0.0.1-dev.60 → 0.0.1-dev.61

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.
@@ -0,0 +1,157 @@
1
+ <script lang="ts">
2
+ import { cn } from '../index.js';
3
+ import type { ClassValue } from 'tailwind-variants';
4
+ import type { Component } from 'svelte';
5
+ import type { FilterTab, FilterGroup, CompactFiltersProps } from '../index.js';
6
+
7
+ // Props definition
8
+ let {
9
+ filterGroups = [],
10
+ isExpanded = $bindable(false),
11
+ title = 'Filters',
12
+ class: className,
13
+ summaryClass,
14
+ expandedClass,
15
+ ChevronDownIcon,
16
+ ChevronUpIcon,
17
+ FilterIcon
18
+ }: CompactFiltersProps = $props();
19
+
20
+ // Toggle expanded state
21
+ function toggleExpanded() {
22
+ isExpanded = !isExpanded;
23
+ }
24
+
25
+ // Helper to get the label of the selected filter
26
+ function getSelectedLabel(tabs: FilterTab[], selectedValue: string): string {
27
+ const tab = tabs.find((tab) => tab.value === selectedValue);
28
+ return tab ? tab.label : 'All';
29
+ }
30
+ </script>
31
+
32
+ {#snippet DefaultFilterIcon()}
33
+ <svg
34
+ width="16"
35
+ height="16"
36
+ viewBox="0 0 24 24"
37
+ fill="none"
38
+ stroke="currentColor"
39
+ stroke-width="2"
40
+ stroke-linecap="round"
41
+ stroke-linejoin="round"
42
+ >
43
+ <polygon points="22,3 2,3 10,12.46 10,19 14,21 14,12.46"></polygon>
44
+ </svg>
45
+ {/snippet}
46
+
47
+ {#snippet DefaultChevronDown()}
48
+ <svg
49
+ width="18"
50
+ height="18"
51
+ viewBox="0 0 24 24"
52
+ fill="none"
53
+ stroke="currentColor"
54
+ stroke-width="2"
55
+ stroke-linecap="round"
56
+ stroke-linejoin="round"
57
+ >
58
+ <polyline points="6,9 12,15 18,9"></polyline>
59
+ </svg>
60
+ {/snippet}
61
+
62
+ {#snippet DefaultChevronUp()}
63
+ <svg
64
+ width="18"
65
+ height="18"
66
+ viewBox="0 0 24 24"
67
+ fill="none"
68
+ stroke="currentColor"
69
+ stroke-width="2"
70
+ stroke-linecap="round"
71
+ stroke-linejoin="round"
72
+ >
73
+ <polyline points="18,15 12,9 6,15"></polyline>
74
+ </svg>
75
+ {/snippet}
76
+
77
+ <div class={cn('rounded-lg border border-gray-200 bg-white p-3 shadow-sm', className)}>
78
+ <button
79
+ onclick={toggleExpanded}
80
+ class="mb-2 flex min-w-full cursor-pointer items-center justify-between"
81
+ >
82
+ <div class="flex items-center gap-2">
83
+ {#if FilterIcon}
84
+ <FilterIcon size={16} class="text-gray-500" />
85
+ {:else}
86
+ <span class="text-gray-500">
87
+ {@render DefaultFilterIcon()}
88
+ </span>
89
+ {/if}
90
+ <span class="text-sm font-medium">{title}</span>
91
+ </div>
92
+ <div
93
+ class="rounded-md p-1 text-gray-500 hover:bg-gray-100 hover:text-gray-700"
94
+ aria-label={isExpanded ? `Collapse ${title.toLowerCase()}` : `Expand ${title.toLowerCase()}`}
95
+ >
96
+ {#if isExpanded}
97
+ {#if ChevronUpIcon}
98
+ <ChevronUpIcon size={18} />
99
+ {:else}
100
+ <span>{@render DefaultChevronUp()}</span>
101
+ {/if}
102
+ {:else if ChevronDownIcon}
103
+ <ChevronDownIcon size={18} />
104
+ {:else}
105
+ <span>{@render DefaultChevronDown()}></span>
106
+ {/if}
107
+ </div>
108
+ </button>
109
+
110
+ {#if !isExpanded}
111
+ <!-- Summary of selected filters when collapsed -->
112
+ <div class={cn('flex flex-wrap gap-2', summaryClass)}>
113
+ {#each filterGroups as group}
114
+ {#if group.tabs.length > 0}
115
+ <div
116
+ class="bg-primary-50 text-primary-700 border-primary-200 flex items-center gap-1 rounded-full border px-3 py-1 text-xs"
117
+ >
118
+ <span class="font-medium">{group.label}:</span>
119
+ {getSelectedLabel(group.tabs, group.selectedValue)}
120
+ </div>
121
+ {/if}
122
+ {/each}
123
+ </div>
124
+ {:else}
125
+ <div class={cn('flex flex-col gap-2', expandedClass)}>
126
+ {#each filterGroups as group, index}
127
+ {#if group.tabs.length > 0}
128
+ <div
129
+ class={cn(
130
+ 'flex items-center gap-2 pb-2',
131
+ index > 0 ? 'border-t border-gray-100 pt-2' : ''
132
+ )}
133
+ >
134
+ <div class={cn('text-xs font-medium text-gray-500', group.minWidth || 'min-w-[70px]')}>
135
+ {group.label}
136
+ </div>
137
+ <div class="flex flex-wrap gap-2">
138
+ {#each group.tabs as tab}
139
+ <button
140
+ onclick={() => group.onChange(tab.value)}
141
+ class={cn(
142
+ 'rounded-full border px-3 py-1 text-xs font-medium whitespace-nowrap',
143
+ group.selectedValue === tab.value
144
+ ? 'bg-primary-50 text-primary-700 border-primary-200'
145
+ : 'border-gray-200 text-gray-700 hover:bg-gray-50'
146
+ )}
147
+ >
148
+ {tab.label}
149
+ </button>
150
+ {/each}
151
+ </div>
152
+ </div>
153
+ {/if}
154
+ {/each}
155
+ </div>
156
+ {/if}
157
+ </div>
@@ -0,0 +1,5 @@
1
+ import type { Component } from 'svelte';
2
+ import type { CompactFiltersProps } from '../index.js';
3
+ declare const CompactFilters: Component<CompactFiltersProps, {}, "isExpanded">;
4
+ type CompactFilters = ReturnType<typeof CompactFilters>;
5
+ export default CompactFilters;
@@ -0,0 +1 @@
1
+ export { default as CompactFilters } from './CompactFilters.svelte';
@@ -0,0 +1 @@
1
+ export { default as CompactFilters } from './CompactFilters.svelte';
package/dist/index.d.ts CHANGED
@@ -342,12 +342,6 @@ export { default as Select } from './elements/dropdown/Select.svelte';
342
342
  export { default as Card } from './layout/card/Card.svelte';
343
343
  export { default as StatsCard } from './layout/card/StatsCard.svelte';
344
344
  export { default as Alert } from './elements/alert/Alert.svelte';
345
- export type TabItem = {
346
- value: string;
347
- label: string;
348
- icon?: Component;
349
- disabled?: boolean;
350
- };
351
345
  export type TabProps = {
352
346
  value: string;
353
347
  label: string;
@@ -810,3 +804,27 @@ export type RadioPillProps = {
810
804
  errors?: string[];
811
805
  onchange?: (value: string) => void;
812
806
  };
807
+ export type FilterTab = {
808
+ value: string;
809
+ label: string;
810
+ };
811
+ export type FilterGroup = {
812
+ key: string;
813
+ label: string;
814
+ tabs: FilterTab[];
815
+ selectedValue: string;
816
+ onChange: (value: string) => void;
817
+ minWidth?: string;
818
+ };
819
+ export type CompactFiltersProps = {
820
+ filterGroups: FilterGroup[];
821
+ isExpanded?: boolean;
822
+ title?: string;
823
+ class?: ClassValue;
824
+ summaryClass?: ClassValue;
825
+ expandedClass?: ClassValue;
826
+ ChevronDownIcon?: Component;
827
+ ChevronUpIcon?: Component;
828
+ FilterIcon?: Component;
829
+ };
830
+ export { CompactFilters } from './filters/index.js';
package/dist/index.js CHANGED
@@ -69,3 +69,5 @@ export { default as RadioPill } from './forms/RadioPill.svelte';
69
69
  export { default as Progress } from './elements/progress/Progress.svelte';
70
70
  export { default as Accordion } from './elements/accordion/Accordion.svelte';
71
71
  export { default as Timeline } from './elements/timeline/Timeline.svelte';
72
+ // Re-export filters
73
+ export { CompactFilters } from './filters/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makolabs/ripple",
3
- "version": "0.0.1-dev.60",
3
+ "version": "0.0.1-dev.61",
4
4
  "description": "Simple Svelte 5 powered component library ✨",
5
5
  "repository": {
6
6
  "type": "git",