@makolabs/ripple 3.0.0 → 3.0.2

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 (34) hide show
  1. package/dist/elements/accordion/Accordion.svelte +1 -1
  2. package/dist/elements/combobox/ComboBox.svelte +59 -29
  3. package/dist/elements/dropdown/Select.svelte +98 -62
  4. package/dist/elements/dropdown/select.d.ts +3 -108
  5. package/dist/elements/dropdown/select.js +37 -46
  6. package/dist/elements/popover/Popover.svelte +59 -36
  7. package/dist/filters/CompactFilters.svelte +1 -1
  8. package/dist/forms/Checkbox.svelte +24 -9
  9. package/dist/forms/DateRange.svelte +236 -204
  10. package/dist/forms/Input.svelte +18 -18
  11. package/dist/forms/MarketSelector.svelte +1 -1
  12. package/dist/forms/NumberInput.svelte +160 -55
  13. package/dist/forms/RadioGroup.svelte +6 -2
  14. package/dist/forms/SegmentedControl.svelte +1 -1
  15. package/dist/forms/Tags.svelte +32 -11
  16. package/dist/forms/Textarea.svelte +8 -13
  17. package/dist/forms/Toggle.svelte +22 -14
  18. package/dist/forms/calendar/Calendar.svelte +107 -8
  19. package/dist/forms/calendar/calendar-types.d.ts +8 -0
  20. package/dist/forms/date-picker/DatePicker.svelte +11 -14
  21. package/dist/forms/form-size.d.ts +37 -0
  22. package/dist/forms/form-size.js +67 -0
  23. package/dist/forms/form-types.d.ts +33 -0
  24. package/dist/forms/month-picker/MonthPicker.svelte +299 -0
  25. package/dist/forms/month-picker/MonthPicker.svelte.d.ts +4 -0
  26. package/dist/forms/month-picker/month-picker-types.d.ts +22 -0
  27. package/dist/forms/month-picker/month-picker-types.js +1 -0
  28. package/dist/forms/segmented-control.d.ts +2 -2
  29. package/dist/forms/segmented-control.js +18 -15
  30. package/dist/forms/slider.js +35 -28
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +1 -0
  33. package/dist/layout/activity-list/ActivityList.svelte +1 -1
  34. package/package.json +1 -1
@@ -0,0 +1,299 @@
1
+ <script lang="ts">
2
+ import { cn } from '../../helper/cls.js';
3
+ import { buildTestId } from '../../helper/testid.js';
4
+ import { Size } from '../../variants.js';
5
+ import { formSizeTokens } from '../form-size.js';
6
+ import Popover from '../../elements/popover/Popover.svelte';
7
+ import type { MonthPickerProps } from './month-picker-types.js';
8
+
9
+ let {
10
+ name,
11
+ id = name,
12
+ label,
13
+ value = $bindable<Date | null>(null),
14
+ placeholder = 'Select month',
15
+ minDate,
16
+ maxDate,
17
+ clearable = true,
18
+ disabled = false,
19
+ size = Size.MD,
20
+ errors = [],
21
+ class: className = '',
22
+ onselect,
23
+ testId
24
+ }: MonthPickerProps = $props();
25
+
26
+ let open = $state(false);
27
+ let listEl = $state<HTMLDivElement | undefined>();
28
+ const tokens = $derived(formSizeTokens[size]);
29
+ const hasErrors = $derived(errors.length > 0);
30
+
31
+ const MONTH_NAMES = [
32
+ 'January',
33
+ 'February',
34
+ 'March',
35
+ 'April',
36
+ 'May',
37
+ 'June',
38
+ 'July',
39
+ 'August',
40
+ 'September',
41
+ 'October',
42
+ 'November',
43
+ 'December'
44
+ ] as const;
45
+
46
+ const MONTH_SHORT = [
47
+ 'Jan',
48
+ 'Feb',
49
+ 'Mar',
50
+ 'Apr',
51
+ 'May',
52
+ 'Jun',
53
+ 'Jul',
54
+ 'Aug',
55
+ 'Sep',
56
+ 'Oct',
57
+ 'Nov',
58
+ 'Dec'
59
+ ] as const;
60
+
61
+ const display = $derived(value ? `${MONTH_NAMES[value.getMonth()]} ${value.getFullYear()}` : '');
62
+
63
+ // Build a flat list of months spanning a range of years. Default:
64
+ // 5 years before → 5 years after the anchor (selected or today).
65
+ const RANGE_YEARS = 5;
66
+ type MonthEntry = { year: number; month: number; date: Date; label: string; disabled: boolean };
67
+
68
+ const anchor = $derived(value ?? new Date());
69
+ const startYear = $derived(minDate ? minDate.getFullYear() : anchor.getFullYear() - RANGE_YEARS);
70
+ const endYear = $derived(maxDate ? maxDate.getFullYear() : anchor.getFullYear() + RANGE_YEARS);
71
+
72
+ const months = $derived.by<MonthEntry[]>(() => {
73
+ const out: MonthEntry[] = [];
74
+ for (let y = startYear; y <= endYear; y++) {
75
+ for (let m = 0; m < 12; m++) {
76
+ const d = new Date(y, m, 1);
77
+ let disabled = false;
78
+ if (minDate && d < new Date(minDate.getFullYear(), minDate.getMonth(), 1)) disabled = true;
79
+ if (maxDate && d > new Date(maxDate.getFullYear(), maxDate.getMonth(), 1)) disabled = true;
80
+ out.push({
81
+ year: y,
82
+ month: m,
83
+ date: d,
84
+ label: MONTH_NAMES[m],
85
+ disabled
86
+ });
87
+ }
88
+ }
89
+ return out;
90
+ });
91
+
92
+ // Unique sorted years and a fast lookup by year*12+month key.
93
+ const years = $derived([...new Set(months.map((e) => e.year))]);
94
+ const monthMap = $derived(new Map(months.map((e) => [e.year * 12 + e.month, e])));
95
+
96
+ function isSelected(entry: MonthEntry): boolean {
97
+ return !!value && value.getFullYear() === entry.year && value.getMonth() === entry.month;
98
+ }
99
+
100
+ function isCurrent(entry: MonthEntry): boolean {
101
+ const now = new Date();
102
+ return entry.year === now.getFullYear() && entry.month === now.getMonth();
103
+ }
104
+
105
+ function pick(entry: MonthEntry) {
106
+ if (entry.disabled) return;
107
+ value = entry.date;
108
+ onselect?.(entry.date);
109
+ open = false;
110
+ }
111
+
112
+ function clear(e: MouseEvent) {
113
+ e.stopPropagation();
114
+ value = null;
115
+ open = false;
116
+ onselect?.(null);
117
+ }
118
+
119
+ function setThisMonth() {
120
+ const now = new Date();
121
+ value = new Date(now.getFullYear(), now.getMonth(), 1);
122
+ onselect?.(value);
123
+ open = false;
124
+ }
125
+
126
+ // Auto-scroll to the selected (or current) month when the panel opens.
127
+ $effect(() => {
128
+ if (!open || !listEl) return;
129
+ requestAnimationFrame(() => {
130
+ const target =
131
+ listEl?.querySelector('[data-selected="true"]') ??
132
+ listEl?.querySelector('[data-current="true"]');
133
+ target?.scrollIntoView({ block: 'center' });
134
+ });
135
+ });
136
+ </script>
137
+
138
+ <div class={cn('w-full', className)}>
139
+ {#if label}
140
+ <label for={id} class="text-default-700 mb-1 block text-sm font-medium">
141
+ {label}
142
+ </label>
143
+ {/if}
144
+
145
+ <input type="hidden" {name} value={value?.toISOString() ?? ''} />
146
+
147
+ <Popover trigger="manual" bind:open placement="bottom" {disabled}>
148
+ <button
149
+ {id}
150
+ type="button"
151
+ {disabled}
152
+ onclick={() => {
153
+ if (!disabled) open = !open;
154
+ }}
155
+ aria-haspopup="dialog"
156
+ aria-expanded={open}
157
+ class={cn(
158
+ 'flex w-full items-center border bg-white transition-colors',
159
+ 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',
160
+ tokens.height,
161
+ tokens.padX,
162
+ tokens.text,
163
+ tokens.gap,
164
+ tokens.radius,
165
+ tokens.shadow,
166
+ hasErrors
167
+ ? 'border-danger-300 focus-visible:border-danger-500 focus-visible:ring-danger-500'
168
+ : 'border-default-300 focus-visible:border-primary-500 focus-visible:ring-primary-500',
169
+ disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'
170
+ )}
171
+ data-testid={buildTestId('month-picker', undefined, testId)}
172
+ >
173
+ <span class={cn('flex-1 text-left', !display && 'text-default-400')}>
174
+ {display || placeholder}
175
+ </span>
176
+ {#if clearable && value && !disabled}
177
+ <span
178
+ role="button"
179
+ tabindex="-1"
180
+ onclick={clear}
181
+ onkeydown={(e) => {
182
+ if (e.key === 'Enter') clear(e as unknown as MouseEvent);
183
+ }}
184
+ aria-label="Clear month"
185
+ class={cn(
186
+ 'text-default-400 hover:text-default-700 flex cursor-pointer items-center justify-center rounded',
187
+ tokens.iconSize
188
+ )}
189
+ >
190
+ <svg class="size-3" viewBox="0 0 12 12" fill="none" aria-hidden="true">
191
+ <path
192
+ d="M3 3l6 6M9 3l-6 6"
193
+ stroke="currentColor"
194
+ stroke-width="1.5"
195
+ stroke-linecap="round"
196
+ />
197
+ </svg>
198
+ </span>
199
+ {/if}
200
+ <svg
201
+ class={cn('text-default-400', tokens.iconSize)}
202
+ viewBox="0 0 20 20"
203
+ fill="currentColor"
204
+ aria-hidden="true"
205
+ >
206
+ <path
207
+ fill-rule="evenodd"
208
+ d="M5.75 2a.75.75 0 0 1 .75.75V4h7V2.75a.75.75 0 0 1 1.5 0V4h.25A2.75 2.75 0 0 1 18 6.75v8.5A2.75 2.75 0 0 1 15.25 18H4.75A2.75 2.75 0 0 1 2 15.25v-8.5A2.75 2.75 0 0 1 4.75 4H5V2.75A.75.75 0 0 1 5.75 2zM4.75 5.5c-.69 0-1.25.56-1.25 1.25V8h13V6.75c0-.69-.56-1.25-1.25-1.25H4.75zM16.5 9.5h-13v5.75c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25V9.5z"
209
+ clip-rule="evenodd"
210
+ />
211
+ </svg>
212
+ </button>
213
+
214
+ {#snippet content({ close })}
215
+ {@render monthGrid(close)}
216
+ {/snippet}
217
+ </Popover>
218
+
219
+ {#if hasErrors}
220
+ <ul class="mt-1 space-y-0.5" role="alert">
221
+ {#each errors as error (error)}
222
+ <li class="text-danger-600 text-xs">{error}</li>
223
+ {/each}
224
+ </ul>
225
+ {/if}
226
+ </div>
227
+
228
+ {#snippet monthGrid(close: () => void)}
229
+ <div class="flex w-full flex-col sm:w-56">
230
+ <div
231
+ bind:this={listEl}
232
+ class="max-h-72 overflow-y-auto [scrollbar-width:none] sm:max-h-72 [&::-webkit-scrollbar]:hidden"
233
+ >
234
+ {#each years as year (year)}
235
+ {@const yearSelected = value?.getFullYear() === year}
236
+ <div
237
+ class={cn(
238
+ 'border-default-200 sticky top-0 z-10 border-b px-3 py-1.5 text-xs font-bold',
239
+ yearSelected ? 'bg-primary-50 text-primary-700' : 'bg-default-50 text-default-800'
240
+ )}
241
+ data-year={year}
242
+ >
243
+ {year}
244
+ </div>
245
+ <div class="grid grid-cols-4 gap-0.5 p-1.5">
246
+ {#each MONTH_SHORT as monthLabel, m (m)}
247
+ {@const entry = monthMap.get(year * 12 + m)}
248
+ {@const sel = entry ? isSelected(entry) : false}
249
+ {@const cur = entry ? isCurrent(entry) : false}
250
+ {@const dis = entry?.disabled ?? true}
251
+ <button
252
+ type="button"
253
+ data-month={m}
254
+ data-selected={sel || undefined}
255
+ data-current={cur || undefined}
256
+ onclick={() => entry && pick(entry)}
257
+ disabled={dis}
258
+ class={cn(
259
+ 'cursor-pointer rounded px-1 py-2 text-xs font-medium transition-colors sm:py-1',
260
+ sel
261
+ ? 'bg-primary-500 text-white'
262
+ : cur
263
+ ? 'text-primary-600 bg-primary-50 ring-primary-300 ring-1'
264
+ : 'text-default-600 hover:bg-default-100',
265
+ dis && 'text-default-300 cursor-not-allowed'
266
+ )}
267
+ >
268
+ {monthLabel}
269
+ </button>
270
+ {/each}
271
+ </div>
272
+ {/each}
273
+ </div>
274
+
275
+ <div class="border-default-200 flex items-center justify-between border-t px-3 py-2">
276
+ {#if clearable}
277
+ <button
278
+ type="button"
279
+ onclick={(e) => {
280
+ clear(e);
281
+ close();
282
+ }}
283
+ class="text-primary-600 cursor-pointer text-xs font-medium hover:underline"
284
+ >
285
+ Clear
286
+ </button>
287
+ {:else}
288
+ <span></span>
289
+ {/if}
290
+ <button
291
+ type="button"
292
+ onclick={setThisMonth}
293
+ class="text-primary-600 cursor-pointer text-xs font-medium hover:underline"
294
+ >
295
+ This month
296
+ </button>
297
+ </div>
298
+ </div>
299
+ {/snippet}
@@ -0,0 +1,4 @@
1
+ import type { MonthPickerProps } from './month-picker-types.js';
2
+ declare const MonthPicker: import("svelte").Component<MonthPickerProps, {}, "value">;
3
+ type MonthPicker = ReturnType<typeof MonthPicker>;
4
+ export default MonthPicker;
@@ -0,0 +1,22 @@
1
+ import type { ClassValue } from 'tailwind-variants';
2
+ import type { VariantSizes } from '../../index.js';
3
+ export type MonthPickerProps = {
4
+ name: string;
5
+ id?: string;
6
+ label?: string;
7
+ /** Bindable selected month. Always the 1st of the month, or null. */
8
+ value?: Date | null;
9
+ placeholder?: string;
10
+ /** Earliest selectable month (inclusive, day is ignored). */
11
+ minDate?: Date;
12
+ /** Latest selectable month (inclusive, day is ignored). */
13
+ maxDate?: Date;
14
+ /** Show a × to clear the selection. @default true */
15
+ clearable?: boolean;
16
+ disabled?: boolean;
17
+ size?: VariantSizes;
18
+ errors?: string[];
19
+ class?: ClassValue;
20
+ onselect?: (value: Date | null) => void;
21
+ testId?: string;
22
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -12,7 +12,7 @@ export declare const segmentedTrack: import("tailwind-variants").TVReturnType<{
12
12
  vertical: string;
13
13
  auto: string;
14
14
  };
15
- }, undefined, "inline-flex max-w-full overflow-x-auto rounded-lg border [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", {
15
+ }, undefined, "flex max-w-full overflow-x-auto rounded-lg border sm:inline-flex [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", {
16
16
  appearance: {
17
17
  surface: string;
18
18
  inverted: string;
@@ -34,7 +34,7 @@ export declare const segmentedTrack: import("tailwind-variants").TVReturnType<{
34
34
  vertical: string;
35
35
  auto: string;
36
36
  };
37
- }, undefined, "inline-flex max-w-full overflow-x-auto rounded-lg border [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", unknown, unknown, undefined>>;
37
+ }, undefined, "flex max-w-full overflow-x-auto rounded-lg border sm:inline-flex [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", unknown, unknown, undefined>>;
38
38
  export declare function segmentClasses(args: {
39
39
  selected: boolean;
40
40
  disabled: boolean;
@@ -1,10 +1,13 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  import { cn } from '../helper/cls.js';
3
- import { Color, Size } from '../variants.js';
3
+ import { Color } from '../variants.js';
4
+ import { formSizeTokens } from './form-size.js';
4
5
  export const segmentedTrack = tv({
5
- // `max-w-full overflow-x-auto` + hidden scrollbar lets a long segment
6
- // row swipe on narrow viewports instead of bleeding past the parent.
7
- base: 'inline-flex max-w-full overflow-x-auto rounded-lg border [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
6
+ // Below `sm`, take full width so the control fills its container on
7
+ // mobile. Above `sm`, shrink to content via `inline-flex`. Either
8
+ // way, `overflow-x-auto` + hidden scrollbar lets a long segment row
9
+ // swipe horizontally without a visible bar.
10
+ base: 'flex max-w-full overflow-x-auto rounded-lg border sm:inline-flex [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
8
11
  variants: {
9
12
  appearance: {
10
13
  surface: 'border-default-200 bg-white p-0',
@@ -36,28 +39,28 @@ const selectedByColor = {
36
39
  [Color.WARNING]: 'bg-warning-600 text-white shadow-sm',
37
40
  [Color.DANGER]: 'bg-danger-600 text-white shadow-sm'
38
41
  };
39
- const segmentSize = {
40
- [Size.XS]: 'gap-1 px-2 py-1 text-xs',
41
- [Size.SM]: 'gap-1.5 px-3 py-1.5 text-xs',
42
- [Size.MD]: 'gap-1.5 px-3 py-1.5 text-sm',
43
- [Size.LG]: 'gap-2 px-4 py-2 text-base',
44
- [Size.XL]: 'gap-2 px-4 py-2.5 text-lg',
45
- [Size.XXL]: 'gap-2 px-5 py-3 text-xl'
46
- };
42
+ // Pull padding/text/gap from the shared form-size tokens so a
43
+ // SegmentedControl at `size="md"` coordinates with Input / Select /
44
+ // DateRange / etc. at the same tier. Segments don't use `height` —
45
+ // their height falls out of text + padding.
46
+ function segmentSize(size) {
47
+ const t = formSizeTokens[size];
48
+ return `${t.gap} ${t.padX} ${t.padY} ${t.text}`;
49
+ }
47
50
  export function segmentClasses(args) {
48
51
  const { selected, disabled, appearance, color, size } = args;
49
52
  if (appearance === 'pills') {
50
- const pillBase = cn('flex cursor-pointer items-center justify-center rounded-full font-medium transition-colors duration-150 shrink-0 whitespace-nowrap', 'focus-visible:ring-primary-500 focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-offset-2', segmentSize[size], disabled && 'cursor-not-allowed opacity-50');
53
+ const pillBase = cn('flex cursor-pointer items-center justify-center rounded-full font-medium transition-colors duration-150 flex-1 whitespace-nowrap sm:flex-initial sm:shrink-0', 'focus-visible:ring-primary-500 focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-offset-2', segmentSize(size), disabled && 'cursor-not-allowed opacity-50');
51
54
  if (disabled)
52
55
  return cn(pillBase, 'text-default-400');
53
56
  if (selected)
54
57
  return cn(pillBase, selectedByColor[color]);
55
58
  return cn(pillBase, 'bg-default-100 text-default-700 hover:bg-default-200');
56
59
  }
57
- const base = cn('flex cursor-pointer items-center justify-center font-medium transition-colors duration-150 shrink-0 whitespace-nowrap', 'focus-visible:ring-primary-500 focus-visible:ring-2 focus-visible:outline-none', appearance === 'inverted' ? 'focus-visible:ring-offset-0' : 'focus-visible:ring-offset-2',
60
+ const base = cn('flex cursor-pointer items-center justify-center font-medium transition-colors duration-150 flex-1 whitespace-nowrap sm:flex-initial sm:shrink-0', 'focus-visible:ring-primary-500 focus-visible:ring-2 focus-visible:outline-none', appearance === 'inverted' ? 'focus-visible:ring-offset-0' : 'focus-visible:ring-offset-2',
58
61
  // Inverted track has p-0.5 padding around segments — give them inner radius
59
62
  // so selected segments don't render as square boxes (matches surface look).
60
- appearance === 'inverted' && 'rounded-md', segmentSize[size], disabled && 'cursor-not-allowed opacity-50');
63
+ appearance === 'inverted' && 'rounded-md', segmentSize(size), disabled && 'cursor-not-allowed opacity-50');
61
64
  if (disabled) {
62
65
  return cn(base, 'text-default-400');
63
66
  }
@@ -1,62 +1,69 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  import { Size } from '../variants.js';
3
+ import { formSizeTokens } from './form-size.js';
4
+ // Track/thumb dimensions are Slider-specific — a "size" for a slider
5
+ // means the physical rail, not an input height. We keep these tuned per
6
+ // tier but pull `text` classes from the shared form-size tokens so a
7
+ // Slider's label reads the same size as an adjacent Input's text.
8
+ const textFor = (size) => formSizeTokens[size].text;
3
9
  export const slider = tv({
4
10
  slots: {
5
11
  base: 'relative w-full',
6
- track: 'absolute h-2 w-full rounded-full bg-default-200 cursor-pointer',
12
+ track: 'absolute w-full rounded-full bg-default-200 cursor-pointer',
7
13
  range: 'absolute h-full rounded-full bg-primary-500',
8
14
  thumb: [
9
15
  'absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white border-2 border-primary-500',
10
16
  'focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2',
11
17
  'hover:scale-110 transition-transform cursor-pointer'
12
18
  ],
13
- mark: 'absolute text-sm text-default-500 -translate-x-1/2',
14
- label: 'mb-2 block text-sm font-medium text-default-700',
15
- value: 'mt-1 text-sm text-default-500'
19
+ mark: 'absolute text-default-500 -translate-x-1/2',
20
+ label: 'mb-2 block font-medium text-default-700',
21
+ value: 'mt-1 text-default-500'
16
22
  },
17
23
  variants: {
18
24
  size: {
19
25
  [Size.XS]: {
20
- track: 'h-1',
21
- thumb: 'w-3 h-3',
22
- mark: 'text-xs top-4',
23
- label: 'text-xs',
24
- value: 'text-xs'
26
+ track: 'h-0.5',
27
+ thumb: 'w-2.5 h-2.5',
28
+ mark: `${textFor(Size.XS)} top-3`,
29
+ label: textFor(Size.XS),
30
+ value: textFor(Size.XS)
25
31
  },
26
32
  [Size.SM]: {
27
33
  track: 'h-1',
28
34
  thumb: 'w-3 h-3',
29
- mark: 'text-xs top-4',
30
- label: 'text-xs',
31
- value: 'text-xs'
35
+ mark: `${textFor(Size.SM)} top-4`,
36
+ label: textFor(Size.SM),
37
+ value: textFor(Size.SM)
32
38
  },
33
39
  [Size.MD]: {
34
- track: 'h-2',
35
- thumb: 'w-4 h-4',
36
- mark: 'text-sm top-6',
37
- label: 'text-sm',
38
- value: 'text-sm'
40
+ track: 'h-1.5',
41
+ thumb: 'w-3.5 h-3.5',
42
+ mark: `${textFor(Size.MD)} top-5`,
43
+ label: textFor(Size.MD),
44
+ value: textFor(Size.MD)
39
45
  },
40
46
  [Size.LG]: {
41
- track: 'h-3',
42
- thumb: 'w-5 h-5',
43
- mark: 'text-base top-7',
44
- label: 'text-base',
45
- value: 'text-base'
47
+ track: 'h-2',
48
+ thumb: 'w-4 h-4',
49
+ mark: `${textFor(Size.LG)} top-6`,
50
+ label: textFor(Size.LG),
51
+ value: textFor(Size.LG)
46
52
  },
47
53
  [Size.XL]: {
48
54
  track: 'h-3',
49
55
  thumb: 'w-5 h-5',
50
- mark: 'text-base top-7',
51
- label: 'text-base',
52
- value: 'text-base'
56
+ mark: `${textFor(Size.XL)} top-7`,
57
+ label: textFor(Size.XL),
58
+ value: textFor(Size.XL)
53
59
  },
60
+ // Form controls cap at xl — see `form-size.ts`.
54
61
  [Size.XXL]: {
55
62
  track: 'h-3',
56
63
  thumb: 'w-5 h-5',
57
- mark: 'text-base top-7',
58
- label: 'text-base',
59
- value: 'text-base'
64
+ mark: `${textFor(Size.XXL)} top-7`,
65
+ label: textFor(Size.XXL),
66
+ value: textFor(Size.XXL)
60
67
  }
61
68
  },
62
69
  disabled: {
package/dist/index.d.ts CHANGED
@@ -51,6 +51,7 @@ export type { TooltipProps, TooltipPlacement, TooltipSize, TooltipVariant } from
51
51
  export type { PopoverProps, PopoverPlacement, PopoverTrigger } from './elements/popover/popover-types.js';
52
52
  export type { CalendarProps, CalendarMode } from './forms/calendar/calendar-types.js';
53
53
  export type { DatePickerProps } from './forms/date-picker/date-picker-types.js';
54
+ export type { MonthPickerProps } from './forms/month-picker/month-picker-types.js';
54
55
  export type { ComboBoxProps, ComboBoxItem } from './elements/combobox/combobox-types.js';
55
56
  export type { ContextMenuProps, ContextMenuItem } from './elements/context-menu/context-menu-types.js';
56
57
  export type { AccordionProps } from './elements/accordion/accordion-types.js';
@@ -124,6 +125,7 @@ export { default as NumberInput } from './forms/NumberInput.svelte';
124
125
  export { default as DateRange } from './forms/DateRange.svelte';
125
126
  export { default as Calendar } from './forms/calendar/Calendar.svelte';
126
127
  export { default as DatePicker } from './forms/date-picker/DatePicker.svelte';
128
+ export { default as MonthPicker } from './forms/month-picker/MonthPicker.svelte';
127
129
  export { default as Tags } from './forms/Tags.svelte';
128
130
  export { default as SegmentedControl } from './forms/SegmentedControl.svelte';
129
131
  export { default as MarketSelector } from './forms/MarketSelector.svelte';
package/dist/index.js CHANGED
@@ -112,6 +112,7 @@ export { default as NumberInput } from './forms/NumberInput.svelte';
112
112
  export { default as DateRange } from './forms/DateRange.svelte';
113
113
  export { default as Calendar } from './forms/calendar/Calendar.svelte';
114
114
  export { default as DatePicker } from './forms/date-picker/DatePicker.svelte';
115
+ export { default as MonthPicker } from './forms/month-picker/MonthPicker.svelte';
115
116
  export { default as Tags } from './forms/Tags.svelte';
116
117
  export { default as SegmentedControl } from './forms/SegmentedControl.svelte';
117
118
  export { default as MarketSelector } from './forms/MarketSelector.svelte';
@@ -115,7 +115,7 @@
115
115
  <div class="mb-1 flex justify-between gap-x-4">
116
116
  <div class="flex flex-wrap items-center gap-2">
117
117
  <button
118
- class="text-default-900 text-sm font-medium"
118
+ class="text-default-900 cursor-pointer text-sm font-medium"
119
119
  onclick={() => onitemclick?.(activityItem, index)}
120
120
  >
121
121
  {activityItem.title}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makolabs/ripple",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Simple Svelte 5 powered component library ✨",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {