@moneymap/ui 0.0.4 → 0.0.5

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @moneymap/ui
2
2
 
3
- > **⚠️ Tailwind CSS Required:** This library requires Tailwind CSS to be configured in your project. See [Setup](#setup-required) below.
3
+ > **⚠️ Tailwind CSS v3 Required:** This library requires Tailwind CSS to be configured in your project. See [Setup](#setup-required) below.
4
4
 
5
5
  ## Setup Required
6
6
 
@@ -113,45 +113,6 @@ module.exports = {
113
113
  }
114
114
  ```
115
115
 
116
- ### Tailwind CSS v4 Setup (Beta)
117
-
118
- 1. **Install Tailwind CSS v4:**
119
-
120
- ```bash
121
- npm install tailwindcss@next @tailwindcss/postcss@next
122
- ```
123
-
124
- 2. **Configure PostCSS** (`postcss.config.js`):
125
-
126
- ```javascript
127
- module.exports = {
128
- plugins: {
129
- '@tailwindcss/postcss': {},
130
- },
131
- };
132
- ```
133
-
134
- 3. **Import Tailwind in your CSS:**
135
-
136
- ```css
137
- @import 'tailwindcss';
138
-
139
- @theme {
140
- --color-border: oklch(0.9 0 0);
141
- --color-input: oklch(0.9 0 0);
142
- --color-ring: oklch(0.2 0 0);
143
- --color-background: oklch(1 0 0);
144
- --color-foreground: oklch(0.15 0 0);
145
- /* Add other custom colors */
146
- }
147
- ```
148
-
149
- 4. **Scan the library** - Tailwind v4 auto-detects imports, but you can configure it in your CSS:
150
-
151
- ```css
152
- @source "../../node_modules/@moneymap/ui/**/*.{js,jsx,ts,tsx}";
153
- ```
154
-
155
116
  ---
156
117
 
157
118
  # Maintainers
package/dist/index.esm.js CHANGED
@@ -70,7 +70,7 @@ function _object_without_properties_loose$j(source, excluded) {
70
70
  }
71
71
  return target;
72
72
  }
73
- var alertVariants = cva('relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', {
73
+ var alertVariants = cva('relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7', {
74
74
  variants: {
75
75
  variant: {
76
76
  default: 'bg-card text-card-foreground',
@@ -11555,7 +11555,7 @@ function Calendar(_param) {
11555
11555
  var defaultClassNames = getDefaultClassNames();
11556
11556
  return jsx(DayPicker, _object_spread$2({
11557
11557
  showOutsideDays: showOutsideDays,
11558
- className: cn('bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent', String.raw(_templateObject()), String.raw(_templateObject1()), className),
11558
+ className: cn('bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent', String.raw(_templateObject()), String.raw(_templateObject1()), className),
11559
11559
  captionLayout: captionLayout,
11560
11560
  formatters: _object_spread$2({
11561
11561
  formatMonthDropdown: function(date) {
@@ -11566,30 +11566,30 @@ function Calendar(_param) {
11566
11566
  }, formatters),
11567
11567
  classNames: _object_spread$2({
11568
11568
  root: cn('w-fit', defaultClassNames.root),
11569
- months: cn('flex gap-4 flex-col md:flex-row relative', defaultClassNames.months),
11570
- month: cn('flex flex-col w-full gap-4', defaultClassNames.month),
11571
- nav: cn('flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between', defaultClassNames.nav),
11569
+ months: cn('relative flex flex-col gap-4 md:flex-row', defaultClassNames.months),
11570
+ month: cn('flex w-full flex-col gap-4', defaultClassNames.month),
11571
+ nav: cn('absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', defaultClassNames.nav),
11572
11572
  button_previous: cn(buttonVariants({
11573
11573
  variant: buttonVariant
11574
- }), 'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none', defaultClassNames.button_previous),
11574
+ }), 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50', defaultClassNames.button_previous),
11575
11575
  button_next: cn(buttonVariants({
11576
11576
  variant: buttonVariant
11577
- }), 'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none', defaultClassNames.button_next),
11578
- month_caption: cn('flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)', defaultClassNames.month_caption),
11579
- dropdowns: cn('w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5', defaultClassNames.dropdowns),
11580
- dropdown_root: cn('relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md', defaultClassNames.dropdown_root),
11581
- dropdown: cn('absolute bg-popover inset-0 opacity-0', defaultClassNames.dropdown),
11582
- caption_label: cn('select-none font-medium', captionLayout === 'label' ? 'text-sm' : 'rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5', defaultClassNames.caption_label),
11577
+ }), 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50', defaultClassNames.button_next),
11578
+ month_caption: cn('flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]', defaultClassNames.month_caption),
11579
+ dropdowns: cn('flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium', defaultClassNames.dropdowns),
11580
+ dropdown_root: cn('has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border', defaultClassNames.dropdown_root),
11581
+ dropdown: cn('absolute inset-0 opacity-0', defaultClassNames.dropdown),
11582
+ caption_label: cn('select-none font-medium', captionLayout === 'label' ? 'text-sm' : '[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5', defaultClassNames.caption_label),
11583
11583
  table: 'w-full border-collapse',
11584
11584
  weekdays: cn('flex', defaultClassNames.weekdays),
11585
- weekday: cn('text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none', defaultClassNames.weekday),
11586
- week: cn('flex w-full mt-2', defaultClassNames.week),
11587
- week_number_header: cn('select-none w-(--cell-size)', defaultClassNames.week_number_header),
11588
- week_number: cn('text-[0.8rem] select-none text-muted-foreground', defaultClassNames.week_number),
11585
+ weekday: cn('text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal', defaultClassNames.weekday),
11586
+ week: cn('mt-2 flex w-full', defaultClassNames.week),
11587
+ week_number_header: cn('w-[--cell-size] select-none', defaultClassNames.week_number_header),
11588
+ week_number: cn('text-muted-foreground select-none text-[0.8rem]', defaultClassNames.week_number),
11589
11589
  day: cn('relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none', props.showWeekNumber ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-md' : '[&:first-child[data-selected=true]_button]:rounded-l-md', defaultClassNames.day),
11590
- range_start: cn('rounded-l-md bg-accent', defaultClassNames.range_start),
11590
+ range_start: cn('bg-accent rounded-l-md', defaultClassNames.range_start),
11591
11591
  range_middle: cn('rounded-none', defaultClassNames.range_middle),
11592
- range_end: cn('rounded-r-md bg-accent', defaultClassNames.range_end),
11592
+ range_end: cn('bg-accent rounded-r-md', defaultClassNames.range_end),
11593
11593
  today: cn('bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none', defaultClassNames.today),
11594
11594
  outside: cn('text-muted-foreground aria-selected:text-muted-foreground', defaultClassNames.outside),
11595
11595
  disabled: cn('text-muted-foreground opacity-50', defaultClassNames.disabled),
@@ -11633,7 +11633,7 @@ function Calendar(_param) {
11633
11633
  ]);
11634
11634
  return jsx("td", _object_spread_props(_object_spread$2({}, props), {
11635
11635
  children: jsx("div", {
11636
- className: "flex size-(--cell-size) items-center justify-center text-center",
11636
+ className: "flex size-[--cell-size] items-center justify-center text-center",
11637
11637
  children: children
11638
11638
  })
11639
11639
  }));
@@ -11664,7 +11664,7 @@ function CalendarDayButton(_param) {
11664
11664
  "data-range-start": modifiers.range_start,
11665
11665
  "data-range-end": modifiers.range_end,
11666
11666
  "data-range-middle": modifiers.range_middle,
11667
- className: cn('data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70', defaultClassNames.day, className)
11667
+ className: cn('data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70', defaultClassNames.day, className)
11668
11668
  }, props));
11669
11669
  }
11670
11670
 
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { DayPicker, type DayButton } from 'react-day-picker';
2
+ import { DayButton, DayPicker } from 'react-day-picker';
3
3
  import { Button } from '../button';
4
4
  declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, formatters, components, ...props }: React.ComponentProps<typeof DayPicker> & {
5
5
  buttonVariant?: React.ComponentProps<typeof Button>['variant'];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/calendar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EACL,SAAS,EAET,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,MAAM,EAAkB,MAAM,WAAW,CAAC;AAEnD,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,UAAU,EACV,eAAsB,EACtB,aAAuB,EACvB,aAAuB,EACvB,UAAU,EACV,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC;CAChE,2CAuJA;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,2CA+BxC;AAED,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/calendar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAwB,MAAM,kBAAkB,CAAC;AAG9E,OAAO,EAAE,MAAM,EAAkB,MAAM,WAAW,CAAC;AAEnD,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,UAAU,EACV,eAAsB,EACtB,aAAuB,EACvB,aAAuB,EACvB,UAAU,EACV,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC;CAChE,2CAoJA;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,2CA+BxC;AAED,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneymap/ui",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from 'class-variance-authority';
4
4
  import { cn } from '../../lib/cn';
5
5
 
6
6
  const alertVariants = cva(
7
- 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
7
+ 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7',
8
8
  {
9
9
  variants: {
10
10
  variant: {
@@ -1,218 +1,211 @@
1
- import * as React from 'react';
2
- import {
3
- ChevronDownIcon,
4
- ChevronLeftIcon,
5
- ChevronRightIcon,
6
- } from 'lucide-react';
7
- import {
8
- DayPicker,
9
- getDefaultClassNames,
10
- type DayButton,
11
- } from 'react-day-picker';
12
-
13
- import { cn } from '../../lib/cn';
14
- import { Button, buttonVariants } from '../button';
15
-
16
- function Calendar({
17
- className,
18
- classNames,
19
- showOutsideDays = true,
20
- captionLayout = 'label',
21
- buttonVariant = 'ghost',
22
- formatters,
23
- components,
24
- ...props
25
- }: React.ComponentProps<typeof DayPicker> & {
26
- buttonVariant?: React.ComponentProps<typeof Button>['variant'];
27
- }) {
28
- const defaultClassNames = getDefaultClassNames();
29
-
30
- return (
31
- <DayPicker
32
- showOutsideDays={showOutsideDays}
33
- className={cn(
34
- 'bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent',
35
- String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
36
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
37
- className,
38
- )}
39
- captionLayout={captionLayout}
40
- formatters={{
41
- formatMonthDropdown: (date) =>
42
- date.toLocaleString('default', { month: 'short' }),
43
- ...formatters,
44
- }}
45
- classNames={{
46
- root: cn('w-fit', defaultClassNames.root),
47
- months: cn(
48
- 'flex gap-4 flex-col md:flex-row relative',
49
- defaultClassNames.months,
50
- ),
51
- month: cn('flex flex-col w-full gap-4', defaultClassNames.month),
52
- nav: cn(
53
- 'flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between',
54
- defaultClassNames.nav,
55
- ),
56
- button_previous: cn(
57
- buttonVariants({ variant: buttonVariant }),
58
- 'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none',
59
- defaultClassNames.button_previous,
60
- ),
61
- button_next: cn(
62
- buttonVariants({ variant: buttonVariant }),
63
- 'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none',
64
- defaultClassNames.button_next,
65
- ),
66
- month_caption: cn(
67
- 'flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)',
68
- defaultClassNames.month_caption,
69
- ),
70
- dropdowns: cn(
71
- 'w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5',
72
- defaultClassNames.dropdowns,
73
- ),
74
- dropdown_root: cn(
75
- 'relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md',
76
- defaultClassNames.dropdown_root,
77
- ),
78
- dropdown: cn(
79
- 'absolute bg-popover inset-0 opacity-0',
80
- defaultClassNames.dropdown,
81
- ),
82
- caption_label: cn(
83
- 'select-none font-medium',
84
- captionLayout === 'label'
85
- ? 'text-sm'
86
- : 'rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5',
87
- defaultClassNames.caption_label,
88
- ),
89
- table: 'w-full border-collapse',
90
- weekdays: cn('flex', defaultClassNames.weekdays),
91
- weekday: cn(
92
- 'text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none',
93
- defaultClassNames.weekday,
94
- ),
95
- week: cn('flex w-full mt-2', defaultClassNames.week),
96
- week_number_header: cn(
97
- 'select-none w-(--cell-size)',
98
- defaultClassNames.week_number_header,
99
- ),
100
- week_number: cn(
101
- 'text-[0.8rem] select-none text-muted-foreground',
102
- defaultClassNames.week_number,
103
- ),
104
- day: cn(
105
- 'relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none',
106
- props.showWeekNumber
107
- ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-md'
108
- : '[&:first-child[data-selected=true]_button]:rounded-l-md',
109
- defaultClassNames.day,
110
- ),
111
- range_start: cn(
112
- 'rounded-l-md bg-accent',
113
- defaultClassNames.range_start,
114
- ),
115
- range_middle: cn('rounded-none', defaultClassNames.range_middle),
116
- range_end: cn('rounded-r-md bg-accent', defaultClassNames.range_end),
117
- today: cn(
118
- 'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',
119
- defaultClassNames.today,
120
- ),
121
- outside: cn(
122
- 'text-muted-foreground aria-selected:text-muted-foreground',
123
- defaultClassNames.outside,
124
- ),
125
- disabled: cn(
126
- 'text-muted-foreground opacity-50',
127
- defaultClassNames.disabled,
128
- ),
129
- hidden: cn('invisible', defaultClassNames.hidden),
130
- ...classNames,
131
- }}
132
- components={{
133
- Root: ({ className, rootRef, ...props }) => {
134
- return (
135
- <div
136
- data-slot="calendar"
137
- ref={rootRef}
138
- className={cn(className)}
139
- {...props}
140
- />
141
- );
142
- },
143
- Chevron: ({ className, orientation, ...props }) => {
144
- if (orientation === 'left') {
145
- return (
146
- <ChevronLeftIcon className={cn('size-4', className)} {...props} />
147
- );
148
- }
149
-
150
- if (orientation === 'right') {
151
- return (
152
- <ChevronRightIcon
153
- className={cn('size-4', className)}
154
- {...props}
155
- />
156
- );
157
- }
158
-
159
- return (
160
- <ChevronDownIcon className={cn('size-4', className)} {...props} />
161
- );
162
- },
163
- DayButton: CalendarDayButton,
164
- WeekNumber: ({ children, ...props }) => {
165
- return (
166
- <td {...props}>
167
- <div className="flex size-(--cell-size) items-center justify-center text-center">
168
- {children}
169
- </div>
170
- </td>
171
- );
172
- },
173
- ...components,
174
- }}
175
- {...props}
176
- />
177
- );
178
- }
179
-
180
- function CalendarDayButton({
181
- className,
182
- day,
183
- modifiers,
184
- ...props
185
- }: React.ComponentProps<typeof DayButton>) {
186
- const defaultClassNames = getDefaultClassNames();
187
-
188
- const ref = React.useRef<HTMLButtonElement>(null);
189
- React.useEffect(() => {
190
- if (modifiers.focused) ref.current?.focus();
191
- }, [modifiers.focused]);
192
-
193
- return (
194
- <Button
195
- ref={ref}
196
- variant="ghost"
197
- size="icon"
198
- data-day={day.date.toLocaleDateString()}
199
- data-selected-single={
200
- modifiers.selected &&
201
- !modifiers.range_start &&
202
- !modifiers.range_end &&
203
- !modifiers.range_middle
204
- }
205
- data-range-start={modifiers.range_start}
206
- data-range-end={modifiers.range_end}
207
- data-range-middle={modifiers.range_middle}
208
- className={cn(
209
- 'data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70',
210
- defaultClassNames.day,
211
- className,
212
- )}
213
- {...props}
214
- />
215
- );
216
- }
217
-
218
- export { Calendar, CalendarDayButton };
1
+ import * as React from 'react';
2
+ import {
3
+ ChevronDownIcon,
4
+ ChevronLeftIcon,
5
+ ChevronRightIcon,
6
+ } from 'lucide-react';
7
+ import { DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker';
8
+
9
+ import { cn } from '../../lib/cn';
10
+ import { Button, buttonVariants } from '../button';
11
+
12
+ function Calendar({
13
+ className,
14
+ classNames,
15
+ showOutsideDays = true,
16
+ captionLayout = 'label',
17
+ buttonVariant = 'ghost',
18
+ formatters,
19
+ components,
20
+ ...props
21
+ }: React.ComponentProps<typeof DayPicker> & {
22
+ buttonVariant?: React.ComponentProps<typeof Button>['variant'];
23
+ }) {
24
+ const defaultClassNames = getDefaultClassNames();
25
+
26
+ return (
27
+ <DayPicker
28
+ showOutsideDays={showOutsideDays}
29
+ className={cn(
30
+ 'bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent',
31
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
32
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
33
+ className,
34
+ )}
35
+ captionLayout={captionLayout}
36
+ formatters={{
37
+ formatMonthDropdown: (date) =>
38
+ date.toLocaleString('default', { month: 'short' }),
39
+ ...formatters,
40
+ }}
41
+ classNames={{
42
+ root: cn('w-fit', defaultClassNames.root),
43
+ months: cn(
44
+ 'relative flex flex-col gap-4 md:flex-row',
45
+ defaultClassNames.months,
46
+ ),
47
+ month: cn('flex w-full flex-col gap-4', defaultClassNames.month),
48
+ nav: cn(
49
+ 'absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1',
50
+ defaultClassNames.nav,
51
+ ),
52
+ button_previous: cn(
53
+ buttonVariants({ variant: buttonVariant }),
54
+ 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50',
55
+ defaultClassNames.button_previous,
56
+ ),
57
+ button_next: cn(
58
+ buttonVariants({ variant: buttonVariant }),
59
+ 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50',
60
+ defaultClassNames.button_next,
61
+ ),
62
+ month_caption: cn(
63
+ 'flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]',
64
+ defaultClassNames.month_caption,
65
+ ),
66
+ dropdowns: cn(
67
+ 'flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium',
68
+ defaultClassNames.dropdowns,
69
+ ),
70
+ dropdown_root: cn(
71
+ 'has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border',
72
+ defaultClassNames.dropdown_root,
73
+ ),
74
+ dropdown: cn('absolute inset-0 opacity-0', defaultClassNames.dropdown),
75
+ caption_label: cn(
76
+ 'select-none font-medium',
77
+ captionLayout === 'label'
78
+ ? 'text-sm'
79
+ : '[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5',
80
+ defaultClassNames.caption_label,
81
+ ),
82
+ table: 'w-full border-collapse',
83
+ weekdays: cn('flex', defaultClassNames.weekdays),
84
+ weekday: cn(
85
+ 'text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal',
86
+ defaultClassNames.weekday,
87
+ ),
88
+ week: cn('mt-2 flex w-full', defaultClassNames.week),
89
+ week_number_header: cn(
90
+ 'w-[--cell-size] select-none',
91
+ defaultClassNames.week_number_header,
92
+ ),
93
+ week_number: cn(
94
+ 'text-muted-foreground select-none text-[0.8rem]',
95
+ defaultClassNames.week_number,
96
+ ),
97
+ day: cn(
98
+ 'relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none',
99
+ props.showWeekNumber
100
+ ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-md'
101
+ : '[&:first-child[data-selected=true]_button]:rounded-l-md',
102
+ defaultClassNames.day,
103
+ ),
104
+ range_start: cn(
105
+ 'bg-accent rounded-l-md',
106
+ defaultClassNames.range_start,
107
+ ),
108
+ range_middle: cn('rounded-none', defaultClassNames.range_middle),
109
+ range_end: cn('bg-accent rounded-r-md', defaultClassNames.range_end),
110
+ today: cn(
111
+ 'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',
112
+ defaultClassNames.today,
113
+ ),
114
+ outside: cn(
115
+ 'text-muted-foreground aria-selected:text-muted-foreground',
116
+ defaultClassNames.outside,
117
+ ),
118
+ disabled: cn(
119
+ 'text-muted-foreground opacity-50',
120
+ defaultClassNames.disabled,
121
+ ),
122
+ hidden: cn('invisible', defaultClassNames.hidden),
123
+ ...classNames,
124
+ }}
125
+ components={{
126
+ Root: ({ className, rootRef, ...props }) => {
127
+ return (
128
+ <div
129
+ data-slot="calendar"
130
+ ref={rootRef}
131
+ className={cn(className)}
132
+ {...props}
133
+ />
134
+ );
135
+ },
136
+ Chevron: ({ className, orientation, ...props }) => {
137
+ if (orientation === 'left') {
138
+ return (
139
+ <ChevronLeftIcon className={cn('size-4', className)} {...props} />
140
+ );
141
+ }
142
+
143
+ if (orientation === 'right') {
144
+ return (
145
+ <ChevronRightIcon
146
+ className={cn('size-4', className)}
147
+ {...props}
148
+ />
149
+ );
150
+ }
151
+
152
+ return (
153
+ <ChevronDownIcon className={cn('size-4', className)} {...props} />
154
+ );
155
+ },
156
+ DayButton: CalendarDayButton,
157
+ WeekNumber: ({ children, ...props }) => {
158
+ return (
159
+ <td {...props}>
160
+ <div className="flex size-[--cell-size] items-center justify-center text-center">
161
+ {children}
162
+ </div>
163
+ </td>
164
+ );
165
+ },
166
+ ...components,
167
+ }}
168
+ {...props}
169
+ />
170
+ );
171
+ }
172
+
173
+ function CalendarDayButton({
174
+ className,
175
+ day,
176
+ modifiers,
177
+ ...props
178
+ }: React.ComponentProps<typeof DayButton>) {
179
+ const defaultClassNames = getDefaultClassNames();
180
+
181
+ const ref = React.useRef<HTMLButtonElement>(null);
182
+ React.useEffect(() => {
183
+ if (modifiers.focused) ref.current?.focus();
184
+ }, [modifiers.focused]);
185
+
186
+ return (
187
+ <Button
188
+ ref={ref}
189
+ variant="ghost"
190
+ size="icon"
191
+ data-day={day.date.toLocaleDateString()}
192
+ data-selected-single={
193
+ modifiers.selected &&
194
+ !modifiers.range_start &&
195
+ !modifiers.range_end &&
196
+ !modifiers.range_middle
197
+ }
198
+ data-range-start={modifiers.range_start}
199
+ data-range-end={modifiers.range_end}
200
+ data-range-middle={modifiers.range_middle}
201
+ className={cn(
202
+ 'data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70',
203
+ defaultClassNames.day,
204
+ className,
205
+ )}
206
+ {...props}
207
+ />
208
+ );
209
+ }
210
+
211
+ export { Calendar, CalendarDayButton };
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
- export * from './components/alert';
2
- export * from './components/alert-dialog';
3
- export * from './components/badge';
4
- export * from './components/button';
5
- export * from './components/button-group';
6
- export * from './components/calendar';
7
- export * from './components/input';
8
- export * from './components/separator';
9
- export * from './components/textarea';
1
+ export * from './components/alert';
2
+ export * from './components/alert-dialog';
3
+ export * from './components/badge';
4
+ export * from './components/button';
5
+ export * from './components/button-group';
6
+ export * from './components/calendar';
7
+ export * from './components/input';
8
+ export * from './components/separator';
9
+ export * from './components/textarea';