rangeflow 1.0.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.
Files changed (53) hide show
  1. package/README.md +523 -0
  2. package/dist/Root.d.ts +1 -0
  3. package/dist/animations/OdometerText.d.ts +6 -0
  4. package/dist/components/Calendar/CalendarDayButton.d.ts +2 -0
  5. package/dist/components/Calendar/Chevron.d.ts +2 -0
  6. package/dist/components/Calendar/index.d.ts +2 -0
  7. package/dist/components/DateSlider/DateLabelsTrack.d.ts +1 -0
  8. package/dist/components/DateSlider/DateTickers.d.ts +1 -0
  9. package/dist/components/DateSlider/RangeStepButton.d.ts +7 -0
  10. package/dist/components/DateSlider/Slider/SliderLeftSpacer.d.ts +1 -0
  11. package/dist/components/DateSlider/Slider/SliderRightSpacer.d.ts +1 -0
  12. package/dist/components/DateSlider/Slider/SliderThumb.d.ts +5 -0
  13. package/dist/components/DateSlider/Slider/index.d.ts +5 -0
  14. package/dist/components/DateSlider/SliderTrack.d.ts +5 -0
  15. package/dist/components/DateSlider/SliderValue.d.ts +1 -0
  16. package/dist/components/DateSlider/index.d.ts +1 -0
  17. package/dist/components/DateSlider/utils/restrict-inner-to-element.d.ts +14 -0
  18. package/dist/components/PickerBar/CalendarPopover.d.ts +6 -0
  19. package/dist/components/PickerBar/SelectedDate.d.ts +1 -0
  20. package/dist/components/PickerBar/index.d.ts +1 -0
  21. package/dist/components/Popover/index.d.ts +8 -0
  22. package/dist/components/RangeTabs/hooks/use-apply-slider-layout.d.ts +1 -0
  23. package/dist/components/RangeTabs/index.d.ts +1 -0
  24. package/dist/constants/date-ranges.d.ts +2 -0
  25. package/dist/constants/slider.d.ts +4 -0
  26. package/dist/context/ContextProvider.d.ts +7 -0
  27. package/dist/context/hooks/use-context-api.d.ts +3 -0
  28. package/dist/context/hooks/use-context-events.d.ts +3 -0
  29. package/dist/context/hooks/use-context-refs.d.ts +2 -0
  30. package/dist/context/hooks/use-context-slots.d.ts +2 -0
  31. package/dist/context/root.d.ts +43 -0
  32. package/dist/entry.d.ts +3 -0
  33. package/dist/hooks/use-days-in-range.d.ts +2 -0
  34. package/dist/hooks/use-emit-date-change.d.ts +1 -0
  35. package/dist/hooks/use-rangeflow-events.d.ts +1 -0
  36. package/dist/hooks/use-rangeflow-refs.d.ts +1 -0
  37. package/dist/hooks/use-rangeflow-slots.d.ts +1 -0
  38. package/dist/hooks/use-rangeflow-store-api.d.ts +2 -0
  39. package/dist/hooks/use-rangeflow-store.d.ts +4 -0
  40. package/dist/hooks/use-rangeflow.d.ts +2 -0
  41. package/dist/hooks/use-update-selected-date.d.ts +2 -0
  42. package/dist/icons/CalendarIcon.d.ts +1 -0
  43. package/dist/icons/DoubleChevronLeftIcon.d.ts +1 -0
  44. package/dist/icons/DoubleChevronRightIcon.d.ts +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.js +852 -0
  47. package/dist/style.css +3 -0
  48. package/dist/types.d.ts +58 -0
  49. package/dist/utils/clamp.d.ts +1 -0
  50. package/dist/utils/create-slider-values.d.ts +9 -0
  51. package/dist/utils/derive-selection-from-layout.d.ts +9 -0
  52. package/dist/utils/interpolate.d.ts +3 -0
  53. package/package.json +84 -0
package/README.md ADDED
@@ -0,0 +1,523 @@
1
+ # RangeFlow
2
+
3
+ A fancy date range picker built with React and Tailwind.
4
+
5
+ RangeFlow gives you a date range picker with a smooth slider, quick range tabs, and a popover calendar. It is built for React 18 and 19, ships with a tiny CSS theming layer, and does not touch your app's global styles.
6
+
7
+ ## Features
8
+
9
+ - Drag based range slider that feels natural on mouse and touch.
10
+ - Quick range tabs (like `2 Weeks`, `30 Days`, `90 Days`) with an animated active pill.
11
+ - Popover calendar with one or many months.
12
+ - Full theming with a single CSS variable (`--rangeflow-accent`).
13
+ - Built in dark mode via `.dark` or `[data-theme='dark']`.
14
+ - Slot based customization for every visible part.
15
+ - Imperative API for external controls (buttons, forms, URL sync).
16
+ - Written in TypeScript. Types are shipped with the package.
17
+
18
+ ## Installation
19
+
20
+ Install the package with your favorite package manager.
21
+
22
+ ```bash
23
+ npm install rangeflow
24
+ ```
25
+
26
+ ```bash
27
+ yarn add rangeflow
28
+ ```
29
+
30
+ ```bash
31
+ pnpm add rangeflow
32
+ ```
33
+
34
+ ### Peer dependencies
35
+
36
+ RangeFlow expects React 18 or later.
37
+
38
+ | Package | Version |
39
+ | ----------- | -------- |
40
+ | `react` | `>=18` |
41
+ | `react-dom` | `>=18` |
42
+
43
+ ### Styles
44
+
45
+ RangeFlow ships a single CSS file. Import it once at the root of your app (for example in `main.tsx`, `_app.tsx`, or `layout.tsx`).
46
+
47
+ ```ts
48
+ import 'rangeflow/style.css'
49
+ ```
50
+
51
+ The styles are scoped to the picker with a `.rangeflow-date-picker` class, so they will not leak into the rest of your app.
52
+
53
+ ## Quick start
54
+
55
+ ```tsx
56
+ import { RangeFlow } from 'rangeflow'
57
+ import 'rangeflow/style.css'
58
+ import dayjs from 'dayjs'
59
+
60
+ export function Example() {
61
+ return (
62
+ <RangeFlow
63
+ defaultRange={{
64
+ from: dayjs().subtract(1, 'week').toDate(),
65
+ to: dayjs().add(1, 'week').toDate()
66
+ }}
67
+ defaultSelected={{
68
+ from: dayjs().subtract(1, 'day').toDate(),
69
+ to: dayjs().add(3, 'day').toDate()
70
+ }}
71
+ onChange={date => console.log('range changed:', date)}
72
+ />
73
+ )
74
+ }
75
+ ```
76
+
77
+ That is all you need for a working picker. From here you can add quick ranges, slots, theming, and the imperative API.
78
+
79
+ ## Core concepts
80
+
81
+ RangeFlow has two dates you should know about:
82
+
83
+ | Concept | What it means |
84
+ | ---------------- | ----------------------------------------------------------------------------- |
85
+ | `range` | The full window shown on the slider track. Think of it as the visible scale. |
86
+ | `selected_date` | The actual range the user picks inside that window. This is what `onChange` gives you. |
87
+
88
+ - `defaultRange` sets the initial **window**.
89
+ - `defaultSelected` sets the initial **picked range** inside that window.
90
+ - `ranges` is the list of quick tabs. Clicking a tab changes the **window** to that tab's dates.
91
+
92
+ When the user drags the slider, only the `selected_date` changes. When the user picks a tab, the window changes and the selection snaps to the new scale.
93
+
94
+ ## API
95
+
96
+ ### `<RangeFlow />`
97
+
98
+ Main component. Renders the full picker.
99
+
100
+ #### Props
101
+
102
+ | Prop | Type | Required | Default | Description |
103
+ | ----------------- | ------------------------------------- | -------- | ----------------------------- | --------------------------------------------------------------------------- |
104
+ | `defaultRange` | `{ from: Date; to: Date }` | Yes | ^^ | The starting window shown on the slider. |
105
+ | `defaultSelected` | `{ from: Date; to: Date }` | Yes | ^^ | The starting picked range. Must fit inside `defaultRange`. |
106
+ | `onChange` | `(date: { from: Date; to: Date }) => void` | Yes | ^^ | Called every time the picked range changes. |
107
+ | `ranges` | `RangeListItem[]` | No | A sensible default list | Quick tabs. Each item has `{ label, from, to }`. |
108
+ | `duration` | `{ min: number; max: number }` | No | `undefined` | Min and max number of days the user can pick. |
109
+ | `disabled` | `{ before?: Date; after?: Date }` | No | `undefined` | Disable dates before or after a point. At least one of the two is required. |
110
+ | `calendar` | `boolean` | No | `true` | Show the popover calendar on the left of the header. |
111
+ | `CalendarProps` | `DayPickerProps` from `react-day-picker` | No | `undefined` | Pass through props to the inner calendar (months, locale, modifiers, etc.). |
112
+ | `Slots` | `Slots` | No | `{}` | Replace any visible part with your own component. |
113
+ | `api` | `RangeFlowApi` | No | `undefined` | Hook returned object for external control. See `useRangeflow`. |
114
+
115
+ #### Types
116
+
117
+ ```ts
118
+ type DateRange = { from: Date; to: Date }
119
+
120
+ type RangeListItem = { label: string; from: Date; to: Date }
121
+
122
+ type Bounds = { min: number; max: number }
123
+
124
+ type DateDisabled =
125
+ | { before: Date; after?: Date }
126
+ | { before?: Date; after: Date }
127
+ ```
128
+
129
+ ### `useRangeflow()`
130
+
131
+ Returns an imperative API object. Pass it into `<RangeFlow api={...} />` to control the picker from outside.
132
+
133
+ ```ts
134
+ const rangeflow = useRangeflow()
135
+
136
+ rangeflow.updateRange({ from, to }) // change the window
137
+ rangeflow.updateSelectedDates({ from, to }) // change the picked range
138
+ ```
139
+
140
+ | Method | Signature | What it does |
141
+ | --------------------- | -------------------------------------- | ------------------------------------------------------------ |
142
+ | `updateRange` | `(range: DateRange) => void` | Change the visible window. The slider rescales. |
143
+ | `updateSelectedDates` | `(dates: DateRange) => void` | Change the picked range inside the current window. |
144
+
145
+ ### Slots
146
+
147
+ Every visible part of the picker can be replaced with your own component.
148
+
149
+ ```ts
150
+ interface Slots {
151
+ RangeTabs?: ComponentType
152
+ DateTickers?: ComponentType
153
+ DateLabelsTrack?: ComponentType
154
+ SelectedDate?: ComponentType<{ from: string; to: string }>
155
+ SliderValueLabel?: ComponentType<{ label: string }>
156
+ }
157
+ ```
158
+
159
+ | Slot | Shown at | Props |
160
+ | ------------------ | ---------------------------------------------- | ------------------------------------ |
161
+ | `RangeTabs` | Top right of the header. Quick range tabs. | none |
162
+ | `SelectedDate` | Top left of the header. The current selection. | `{ from: string; to: string }` |
163
+ | `DateTickers` | Small tick marks on the slider track. | none |
164
+ | `DateLabelsTrack` | Labels below or above the slider. | none |
165
+ | `SliderValueLabel` | Label on the slider thumb while dragging. | `{ label: string }` |
166
+
167
+ Any slot you do not pass keeps the default look.
168
+
169
+ ## Theming
170
+
171
+ RangeFlow is themed with CSS variables. You only need to set one to re-skin the whole picker.
172
+
173
+ ```css
174
+ .my-app {
175
+ --rangeflow-accent: #4f46e5;
176
+ }
177
+ ```
178
+
179
+ Everything else (borders, hovers, ranges, rings) is derived with `color-mix()` so the picker stays balanced no matter the accent color.
180
+
181
+ ### Dark mode
182
+
183
+ Dark mode turns on when any of these matches:
184
+
185
+ - The picker has the `dark` class.
186
+ - The picker has `data-theme="dark"`.
187
+ - Any parent has the `dark` class.
188
+ - Any parent has `data-theme="dark"`.
189
+
190
+ This works out of the box with Tailwind's dark mode and with most theming libraries.
191
+
192
+ ### Tokens
193
+
194
+ All tokens are optional. Set only the ones you want to override.
195
+
196
+ | Token | Default | What it controls |
197
+ | ----------------------------- | --------------------------------------- | --------------------------------------------------- |
198
+ | `--rangeflow-accent` | `#16433C` | Brand color. Drives most other tokens. |
199
+ | `--rangeflow-surface` | `#ffffff` (light), `#0a0f0c` (dark) | Background of the picker. |
200
+ | `--rangeflow-foreground` | `#0a0f0c` (light), `#ffffff` (dark) | Text base color. |
201
+ | `--rangeflow-on-accent` | Auto from accent (black or white) | Text color on top of solid accent. |
202
+ | `--rangeflow-bg` | `--rangeflow-surface` | Inner background. |
203
+ | `--rangeflow-border` | Mix of accent and surface | Default border. |
204
+ | `--rangeflow-border-strong` | Mix of accent and surface | Stronger border. |
205
+ | `--rangeflow-shadow-color` | Mix of foreground and transparent | Shadow tint. |
206
+ | `--rangeflow-text` | Near foreground | Main text. |
207
+ | `--rangeflow-text-muted` | Softer text | Secondary text. |
208
+ | `--rangeflow-text-subtle` | Softer text | Labels. |
209
+ | `--rangeflow-text-faint` | Faint text | Separators and faint labels. |
210
+ | `--rangeflow-text-disabled` | Disabled text | Disabled items. |
211
+ | `--rangeflow-hover-bg` | Light accent mix | Hover background. |
212
+ | `--rangeflow-range-bg` | Accent mix | Background of the picked range. |
213
+ | `--rangeflow-active-bg` | Stronger accent mix | Active tab pill background. |
214
+ | `--rangeflow-accent-solid` | `--rangeflow-accent` | Solid accent fills. |
215
+ | `--rangeflow-accent-solid-hover` | Darker accent | Hover state for solid accent. |
216
+ | `--rangeflow-accent-contrast` | `--rangeflow-on-accent` | Text on solid accent. |
217
+ | `--rangeflow-accent-text` | Accent mixed with foreground | Tinted text like the selected date label. |
218
+ | `--rangeflow-ring` | `--rangeflow-accent` | Focus ring. |
219
+ | `--rangeflow-separator` | Accent with transparency | Separator lines. |
220
+ | `--rangeflow-separator-active`| `--rangeflow-accent` | Separator on active state. |
221
+ | `--rangeflow-ticker` | Light accent mix | Tick marks on the slider. |
222
+ | `--rangeflow-today` | Accent text | The "today" marker on the calendar. |
223
+ | `--rangeflow-font` | System font stack | Font family used inside the picker. |
224
+
225
+ ## Examples
226
+
227
+ ### 1. Basic picker
228
+
229
+ ```tsx
230
+ import { RangeFlow } from 'rangeflow'
231
+ import dayjs from 'dayjs'
232
+
233
+ export function Basic() {
234
+ return (
235
+ <RangeFlow
236
+ defaultRange={{
237
+ from: dayjs().subtract(1, 'week').toDate(),
238
+ to: dayjs().add(1, 'week').toDate()
239
+ }}
240
+ defaultSelected={{
241
+ from: dayjs().toDate(),
242
+ to: dayjs().add(3, 'day').toDate()
243
+ }}
244
+ onChange={date => console.log(date)}
245
+ />
246
+ )
247
+ }
248
+ ```
249
+
250
+ ### 2. Custom quick range tabs
251
+
252
+ ```tsx
253
+ <RangeFlow
254
+ defaultRange={{
255
+ from: dayjs().subtract(30, 'day').toDate(),
256
+ to: dayjs().add(30, 'day').toDate()
257
+ }}
258
+ defaultSelected={{
259
+ from: dayjs().toDate(),
260
+ to: dayjs().add(7, 'day').toDate()
261
+ }}
262
+ ranges={[
263
+ {
264
+ label: 'This week',
265
+ from: dayjs().startOf('week').toDate(),
266
+ to: dayjs().endOf('week').toDate()
267
+ },
268
+ {
269
+ label: 'This month',
270
+ from: dayjs().startOf('month').toDate(),
271
+ to: dayjs().endOf('month').toDate()
272
+ },
273
+ {
274
+ label: 'This year',
275
+ from: dayjs().startOf('year').toDate(),
276
+ to: dayjs().endOf('year').toDate()
277
+ }
278
+ ]}
279
+ onChange={console.log}
280
+ />
281
+ ```
282
+
283
+ ### 3. Two month calendar
284
+
285
+ ```tsx
286
+ <RangeFlow
287
+ defaultRange={{ from: dayjs().subtract(1, 'month').toDate(), to: dayjs().add(1, 'month').toDate() }}
288
+ defaultSelected={{ from: dayjs().toDate(), to: dayjs().add(5, 'day').toDate() }}
289
+ CalendarProps={{ numberOfMonths: 2 }}
290
+ onChange={console.log}
291
+ />
292
+ ```
293
+
294
+ ### 4. Min and max duration
295
+
296
+ Stop the user from picking less than 3 days or more than 30.
297
+
298
+ ```tsx
299
+ <RangeFlow
300
+ defaultRange={{ from: dayjs().subtract(2, 'month').toDate(), to: dayjs().add(2, 'month').toDate() }}
301
+ defaultSelected={{ from: dayjs().toDate(), to: dayjs().add(7, 'day').toDate() }}
302
+ duration={{ min: 3, max: 30 }}
303
+ onChange={console.log}
304
+ />
305
+ ```
306
+
307
+ ### 5. Disable past dates
308
+
309
+ ```tsx
310
+ <RangeFlow
311
+ defaultRange={{ from: dayjs().toDate(), to: dayjs().add(60, 'day').toDate() }}
312
+ defaultSelected={{ from: dayjs().toDate(), to: dayjs().add(7, 'day').toDate() }}
313
+ disabled={{ before: dayjs().toDate() }}
314
+ onChange={console.log}
315
+ />
316
+ ```
317
+
318
+ ### 6. Disable future dates
319
+
320
+ ```tsx
321
+ <RangeFlow
322
+ defaultRange={{ from: dayjs().subtract(60, 'day').toDate(), to: dayjs().toDate() }}
323
+ defaultSelected={{ from: dayjs().subtract(7, 'day').toDate(), to: dayjs().toDate() }}
324
+ disabled={{ after: dayjs().toDate() }}
325
+ onChange={console.log}
326
+ />
327
+ ```
328
+
329
+ ### 7. Hide the calendar
330
+
331
+ Keep the slider and tabs, drop the popover calendar.
332
+
333
+ ```tsx
334
+ <RangeFlow
335
+ calendar={false}
336
+ defaultRange={{ from: dayjs().subtract(1, 'week').toDate(), to: dayjs().add(1, 'week').toDate() }}
337
+ defaultSelected={{ from: dayjs().toDate(), to: dayjs().add(3, 'day').toDate() }}
338
+ onChange={console.log}
339
+ />
340
+ ```
341
+
342
+ ### 8. External controls with `useRangeflow`
343
+
344
+ Drive the picker from buttons, forms, or URL params.
345
+
346
+ ```tsx
347
+ import { RangeFlow, useRangeflow } from 'rangeflow'
348
+ import dayjs from 'dayjs'
349
+
350
+ export function WithControls() {
351
+ const rangeflow = useRangeflow()
352
+
353
+ return (
354
+ <div>
355
+ <div style={{ display: 'flex', gap: 8 }}>
356
+ <button
357
+ onClick={() =>
358
+ rangeflow.updateRange({
359
+ from: dayjs().subtract(15, 'day').toDate(),
360
+ to: dayjs().add(15, 'day').toDate()
361
+ })
362
+ }
363
+ >
364
+ 30 day window
365
+ </button>
366
+
367
+ <button
368
+ onClick={() =>
369
+ rangeflow.updateSelectedDates({
370
+ from: dayjs().toDate(),
371
+ to: dayjs().add(7, 'day').toDate()
372
+ })
373
+ }
374
+ >
375
+ Pick next 7 days
376
+ </button>
377
+ </div>
378
+
379
+ <RangeFlow
380
+ api={rangeflow}
381
+ defaultRange={{
382
+ from: dayjs().subtract(1, 'week').toDate(),
383
+ to: dayjs().add(1, 'week').toDate()
384
+ }}
385
+ defaultSelected={{
386
+ from: dayjs().toDate(),
387
+ to: dayjs().add(3, 'day').toDate()
388
+ }}
389
+ onChange={console.log}
390
+ />
391
+ </div>
392
+ )
393
+ }
394
+ ```
395
+
396
+ ### 9. Custom selected date slot
397
+
398
+ ```tsx
399
+ <RangeFlow
400
+ defaultRange={{ from: dayjs().subtract(1, 'week').toDate(), to: dayjs().add(1, 'week').toDate() }}
401
+ defaultSelected={{ from: dayjs().toDate(), to: dayjs().add(3, 'day').toDate() }}
402
+ Slots={{
403
+ SelectedDate: ({ from, to }) => (
404
+ <span style={{ fontWeight: 600 }}>
405
+ {from} → {to}
406
+ </span>
407
+ )
408
+ }}
409
+ onChange={console.log}
410
+ />
411
+ ```
412
+
413
+ ### 10. Custom range tabs slot
414
+
415
+ ```tsx
416
+ <RangeFlow
417
+ defaultRange={{ from: dayjs().subtract(1, 'month').toDate(), to: dayjs().add(1, 'month').toDate() }}
418
+ defaultSelected={{ from: dayjs().toDate(), to: dayjs().add(3, 'day').toDate() }}
419
+ Slots={{
420
+ RangeTabs: () => <MyOwnTabs />
421
+ }}
422
+ onChange={console.log}
423
+ />
424
+ ```
425
+
426
+ ### 11. Theme with one variable
427
+
428
+ ```css
429
+ .my-picker {
430
+ --rangeflow-accent: #4f46e5;
431
+ }
432
+ ```
433
+
434
+ ```tsx
435
+ <div className="my-picker">
436
+ <RangeFlow {...props} />
437
+ </div>
438
+ ```
439
+
440
+ ### 12. Dark mode
441
+
442
+ ```tsx
443
+ <div className="dark">
444
+ <RangeFlow {...props} />
445
+ </div>
446
+ ```
447
+
448
+ Or with a data attribute:
449
+
450
+ ```tsx
451
+ <div data-theme="dark">
452
+ <RangeFlow {...props} />
453
+ </div>
454
+ ```
455
+
456
+ ### 13. Form integration
457
+
458
+ ```tsx
459
+ const [range, setRange] = useState<DateRange>({
460
+ from: dayjs().toDate(),
461
+ to: dayjs().add(3, 'day').toDate()
462
+ })
463
+
464
+ <form onSubmit={() => submit(range)}>
465
+ <RangeFlow
466
+ defaultRange={{ from: dayjs().subtract(1, 'week').toDate(), to: dayjs().add(1, 'week').toDate() }}
467
+ defaultSelected={range}
468
+ onChange={setRange}
469
+ />
470
+
471
+ <input type="hidden" name="from" value={range.from.toISOString()} />
472
+ <input type="hidden" name="to" value={range.to.toISOString()} />
473
+
474
+ <button type="submit">Save</button>
475
+ </form>
476
+ ```
477
+
478
+ ## Accessibility
479
+
480
+ - All buttons use real `<button>` elements.
481
+ - The slider thumb responds to mouse, touch, and pointer drags.
482
+ - Focus rings use `--rangeflow-ring` and work on every interactive item.
483
+ - The calendar is powered by `react-day-picker`, which handles keyboard nav.
484
+
485
+ ## Class name reference
486
+
487
+ Use these class names to style parts of the picker without touching the tokens.
488
+
489
+ | Class | Element |
490
+ | ---------------------------- | ---------------------------------------- |
491
+ | `.rangeflow-date-picker` | Root of the picker. |
492
+ | `.rangeflow-date-picker-portal` | Root of any portalled part (popovers). |
493
+ | `.rangeflow-root` | Outer wrapper. |
494
+ | `.rangeflow-header` | Top bar holding the date and tabs. |
495
+ | `.rangeflow-body` | Bottom area with the slider. |
496
+ | `.rangeflow-slider` | Slider track container. |
497
+ | `.rangeflow-tabs` | Range tabs container. |
498
+ | `.rangeflow-tab` | One tab button. |
499
+ | `.rangeflow-tab-indicator` | Animated active tab pill. |
500
+ | `.rangeflow-selected-date` | The current selection label. |
501
+
502
+ ## Notes for LLMs and AI coding tools
503
+
504
+ If you are an AI tool generating code with RangeFlow, keep these facts in mind:
505
+
506
+ - The package is `rangeflow`. Only two named exports are public: `RangeFlow` (component) and `useRangeflow` (hook). Also a type export `RangeFlowApi`.
507
+ - Always import the CSS file once: `import 'rangeflow/style.css'`.
508
+ - `defaultRange` and `defaultSelected` are required. Both must be `{ from: Date; to: Date }`.
509
+ - `defaultSelected` must fit inside `defaultRange` or the slider will clamp it.
510
+ - `onChange` is required and fires with `{ from: Date; to: Date }`.
511
+ - To drive the picker from outside, call `useRangeflow()` and pass the result to `<RangeFlow api={...} />`. Then use `updateRange` or `updateSelectedDates`.
512
+ - Theming is CSS variable based. Set `--rangeflow-accent` on any parent to re-skin the picker.
513
+ - Dark mode turns on via a `dark` class or `data-theme="dark"` on the picker or any parent.
514
+ - The picker is 560px wide and 140px tall by default (`w-140 h-35` in Tailwind units).
515
+ - Dates are plain JS `Date` objects. The package uses `dayjs` internally but does not require it from you.
516
+
517
+ ## Browser support
518
+
519
+ RangeFlow uses modern CSS features such as `color-mix()` and the OKLCH color space. It works in all current versions of Chrome, Edge, Firefox, and Safari.
520
+
521
+ ## License
522
+
523
+ MIT
package/dist/Root.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function Root(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ type OdometerTextProps = {
2
+ children: string;
3
+ className?: string;
4
+ };
5
+ export declare const OdometerText: import('react').MemoExoticComponent<({ children, className }: OdometerTextProps) => import("react/jsx-runtime").JSX.Element>;
6
+ export {};
@@ -0,0 +1,2 @@
1
+ import { DayButtonProps } from 'react-day-picker';
2
+ export declare function CalendarDayButton({ className, day: _day, modifiers, ...props }: DayButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { ChevronProps } from 'react-day-picker';
2
+ export declare function Chevron({ className, orientation, size }: ChevronProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { DayPickerProps } from 'react-day-picker';
2
+ export declare function Calendar({ captionLayout, className, classNames, components, showOutsideDays, ...props }: DayPickerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const DateLabelsTrack: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
@@ -0,0 +1 @@
1
+ export declare const DateTickers: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ onClick: () => void;
5
+ }
6
+ export declare function RangeStepButton({ children, onClick }: Props): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1 @@
1
+ export declare function SliderLeftSpacer(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function SliderRightSpacer(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ interface Props {
2
+ onHandleRef: (el: HTMLDivElement | null) => void;
3
+ }
4
+ export declare function SliderThumb({ onHandleRef }: Props): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,5 @@
1
+ interface Props {
2
+ onHandleRef: (el: HTMLDivElement | null) => void;
3
+ }
4
+ export declare function Slider({ onHandleRef }: Props): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,5 @@
1
+ interface Props {
2
+ onHandleRef: (el: HTMLDivElement | null) => void;
3
+ }
4
+ export declare function SliderTrack({ onHandleRef }: Props): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1 @@
1
+ export declare const SliderValue: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
@@ -0,0 +1 @@
1
+ export declare function DateSlider(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { Data, DragOperation, Modifier } from '@dnd-kit/abstract';
2
+ import { DragDropManager, Draggable, Droppable } from '@dnd-kit/dom';
3
+ interface Options {
4
+ inner: Element | null | ((operation: DragOperation) => Element | null);
5
+ container: Element | null | ((operation: DragOperation) => Element | null);
6
+ }
7
+ export declare class RestrictInnerToElement extends Modifier<DragDropManager<Data, Draggable, Droppable>, Options> {
8
+ private innerRect;
9
+ private containerRect;
10
+ constructor(manager: DragDropManager<Data, Draggable, Droppable>, options?: Options);
11
+ apply({ transform }: DragOperation): import('@dnd-kit/geometry').Coordinates;
12
+ static configure: (options: Options) => import('@dnd-kit/abstract').PluginDescriptor<any, any, typeof RestrictInnerToElement>;
13
+ }
14
+ export {};
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ }
5
+ export declare function CalendarPopover({ children }: Props): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1 @@
1
+ export declare function SelectedDate(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function PickerBar(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { ComponentProps } from 'react';
2
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
3
+ type ContentProps = ComponentProps<typeof PopoverPrimitive.Content>;
4
+ export declare const PopoverContent: import('react').MemoExoticComponent<({ align, className, sideOffset, children, ...props }: ContentProps) => import("react/jsx-runtime").JSX.Element>;
5
+ export declare const Popover: import('react').FC<PopoverPrimitive.PopoverProps>;
6
+ export declare const PopoverTrigger: import('react').ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
7
+ export declare const PopoverAnchor: import('react').ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & import('react').RefAttributes<HTMLDivElement>>;
8
+ export {};
@@ -0,0 +1 @@
1
+ export declare function useApplySliderLayout(): void;
@@ -0,0 +1 @@
1
+ export declare function RangeTabs(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { RangeListItem } from '../types';
2
+ export declare const DefaultRangesList: RangeListItem[];
@@ -0,0 +1,4 @@
1
+ export declare const SLIDER_LEFT_SPACER = "left-spacer";
2
+ export declare const SLIDER_RIGHT_SPACER = "right-spacer";
3
+ export declare const SLIDER_THUMB = "slider-track-thumb";
4
+ export declare const SLIDER_THUMB_MIN_SIZE = 5;
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+ import { RangeFlowProps } from '../types';
3
+ interface Props extends RangeFlowProps {
4
+ children: ReactNode;
5
+ }
6
+ export declare function ContextProvider({ children, defaultRange, defaultSelected, disabled, duration, calendar, ranges, CalendarProps, Slots, api, onChange }: Props): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,3 @@
1
+ import { RangeFlowApi } from '../../types';
2
+ import { RangeFlowRefs, RangeFlowStore } from '../root';
3
+ export declare function useContextApi(store: RangeFlowStore, refs: RangeFlowRefs, api?: RangeFlowApi): void;
@@ -0,0 +1,3 @@
1
+ import { RangeFlowProps } from '../../types';
2
+ import { RangeFlowEvents } from '../root';
3
+ export declare function useContextEvents({ onChange }: Partial<RangeFlowProps>): RangeFlowEvents;