@juspay/svelte-ui-components 2.63.1 → 2.64.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.
@@ -5,6 +5,7 @@
5
5
  import Calendar from '../Calendar/Calendar.svelte';
6
6
  import Button from '../Button/Button.svelte';
7
7
  import chevronDownSvg from '../assets/chevron-down.svg?raw';
8
+ import checkmarkSvg from '../assets/checkmark.svg?raw';
8
9
 
9
10
  let {
10
11
  rangeStart = $bindable(null),
@@ -16,6 +17,7 @@
16
17
  disabledDates = [],
17
18
  maxRangeDays = null,
18
19
  presets = null,
20
+ presetCheckmark = false,
19
21
  placeholder = 'Select date',
20
22
  dualMonth,
21
23
  timePicker,
@@ -110,6 +112,13 @@
110
112
 
111
113
  let activePresetLabel: string | null = $state(resolvedInitialPresetLabel);
112
114
 
115
+ // The preset whose range is currently committed (seeded from initialPresetLabel,
116
+ // updated on every Apply). Unlike activePresetLabel — which is cleared the moment
117
+ // the user interacts so the trigger can fall back to a date range — this survives
118
+ // the open/apply cycle so re-opening the picker re-highlights the committed preset
119
+ // by label instead of date-matching (which lights up every same-day preset at once).
120
+ let committedPresetLabel: string | null = $state(resolvedInitialPresetLabel);
121
+
113
122
  // Seed draft from initialPresetLabel whenever presets become available so
114
123
  // the calendar shows the preset's date selection when the picker is first
115
124
  // opened — even if presets arrive asynchronously after initial render.
@@ -192,8 +201,9 @@
192
201
  draftCompareStart = compareStart;
193
202
  draftCompareEnd = compareEnd;
194
203
 
195
- // Reset preset tracking so each picker session starts clean.
196
- selectedPresetLabel = null;
204
+ // Re-seed the session from the committed preset so the sidebar re-highlights it
205
+ // by label. A direct calendar click later clears this, reverting to date matching.
206
+ selectedPresetLabel = committedPresetLabel;
197
207
 
198
208
  // Navigate left calendar so it shows the committed start month (or today)
199
209
  const anchor = rangeStart !== null ? rangeStart : value !== null ? value : now;
@@ -264,6 +274,7 @@
264
274
  if (draftStart !== null && draftEnd !== null) {
265
275
  rangeStart = draftStart;
266
276
  rangeEnd = draftEnd;
277
+ committedPresetLabel = selectedPresetLabel;
267
278
  onapply?.({ rangeStart: draftStart, rangeEnd: draftEnd, presetLabel: selectedPresetLabel });
268
279
  }
269
280
  if (
@@ -282,6 +293,7 @@
282
293
  } else {
283
294
  if (draftValue !== null) {
284
295
  value = draftValue;
296
+ committedPresetLabel = selectedPresetLabel;
285
297
  onapplysingle?.({ date: draftValue, presetLabel: selectedPresetLabel });
286
298
  }
287
299
  }
@@ -291,6 +303,7 @@
291
303
  function handleClear(): void {
292
304
  value = null;
293
305
  draftValue = null;
306
+ committedPresetLabel = null;
294
307
  onclear?.();
295
308
  closePicker();
296
309
  }
@@ -545,11 +558,16 @@
545
558
  type="button"
546
559
  class="drp-preset-item"
547
560
  class:drp-preset-active={isPresetActive(preset)}
561
+ class:drp-preset-checkable={presetCheckmark}
548
562
  role="option"
549
563
  aria-selected={isPresetActive(preset)}
550
564
  onclick={() => handlePreset(preset)}
551
565
  >
552
566
  {preset.label}
567
+ {#if presetCheckmark && isPresetActive(preset)}
568
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
569
+ <span class="drp-preset-check" aria-hidden="true">{@html checkmarkSvg}</span>
570
+ {/if}
553
571
  </button>
554
572
  {/each}
555
573
  </div>
@@ -786,6 +804,29 @@
786
804
  background: var(--drp-preset-active-hover-background, #333333);
787
805
  }
788
806
 
807
+ /* Opt-in checkmark layout: reserve a trailing slot so the active preset's tick
808
+ sits flush-right while the label stays left. A preset with no tick (or a
809
+ label-only preset) keeps its single flex child at the start, unchanged. */
810
+ .drp-preset-checkable {
811
+ display: flex;
812
+ align-items: center;
813
+ justify-content: space-between;
814
+ gap: var(--drp-preset-check-gap, 8px);
815
+ }
816
+
817
+ .drp-preset-check {
818
+ display: inline-flex;
819
+ flex-shrink: 0;
820
+ width: var(--drp-preset-check-size, 16px);
821
+ height: var(--drp-preset-check-size, 16px);
822
+ color: var(--drp-preset-check-color, inherit);
823
+ }
824
+
825
+ .drp-preset-check :global(svg) {
826
+ width: 100%;
827
+ height: 100%;
828
+ }
829
+
789
830
  /* ── Calendar area ── */
790
831
  .drp-calendars {
791
832
  display: flex;
@@ -33,6 +33,12 @@ export type OptionalDateRangePickerProperties = {
33
33
  maxRangeDays?: number | null;
34
34
  /** Preset options shown in the sidebar. Omit to hide the sidebar. */
35
35
  presets?: DateRangePreset[] | null;
36
+ /**
37
+ * Show a trailing checkmark on the active preset in the sidebar. Opt-in, so
38
+ * existing layouts are unchanged; the active preset is always distinguished by
39
+ * its highlighted background regardless of this flag. Default: false.
40
+ */
41
+ presetCheckmark?: boolean;
36
42
  /** Placeholder shown when no range is selected. */
37
43
  placeholder?: string;
38
44
  /** Show two months side by side. Defaults to true for range mode, false for single. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.63.1",
3
+ "version": "2.64.1",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",