@udixio/ui-react 2.10.13 → 2.10.15

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 (173) hide show
  1. package/package.json +4 -2
  2. package/.eslintrc.mjs +0 -22
  3. package/.storybook/main.ts +0 -20
  4. package/.storybook/preview.ts +0 -1
  5. package/CHANGELOG.md +0 -1144
  6. package/postcss.config.mjs +0 -5
  7. package/src/index.css +0 -4
  8. package/src/index.ts +0 -1
  9. package/src/lib/components/AnchorPositioner.tsx +0 -185
  10. package/src/lib/components/Button.tsx +0 -208
  11. package/src/lib/components/Card.tsx +0 -47
  12. package/src/lib/components/Carousel.tsx +0 -437
  13. package/src/lib/components/CarouselItem.tsx +0 -61
  14. package/src/lib/components/Checkbox.tsx +0 -120
  15. package/src/lib/components/Chip.tsx +0 -341
  16. package/src/lib/components/Chips.tsx +0 -331
  17. package/src/lib/components/ContextMenu.tsx +0 -109
  18. package/src/lib/components/DatePicker.tsx +0 -432
  19. package/src/lib/components/Divider.tsx +0 -20
  20. package/src/lib/components/Fab.tsx +0 -127
  21. package/src/lib/components/FabMenu.tsx +0 -239
  22. package/src/lib/components/IconButton.tsx +0 -146
  23. package/src/lib/components/Menu.tsx +0 -88
  24. package/src/lib/components/MenuGroup.tsx +0 -34
  25. package/src/lib/components/MenuHeadline.tsx +0 -9
  26. package/src/lib/components/MenuItem.tsx +0 -215
  27. package/src/lib/components/NavigationRail.tsx +0 -186
  28. package/src/lib/components/NavigationRailItem.tsx +0 -227
  29. package/src/lib/components/ProgressIndicator.tsx +0 -214
  30. package/src/lib/components/SideSheet.tsx +0 -135
  31. package/src/lib/components/Slider.tsx +0 -374
  32. package/src/lib/components/Snackbar.tsx +0 -77
  33. package/src/lib/components/Switch.tsx +0 -107
  34. package/src/lib/components/Tab.tsx +0 -123
  35. package/src/lib/components/TabGroup.tsx +0 -66
  36. package/src/lib/components/TabGroupContext.tsx +0 -16
  37. package/src/lib/components/TabPanel.tsx +0 -27
  38. package/src/lib/components/TabPanels.tsx +0 -76
  39. package/src/lib/components/Tabs.tsx +0 -105
  40. package/src/lib/components/TextField.tsx +0 -586
  41. package/src/lib/components/Tooltip.tsx +0 -217
  42. package/src/lib/components/index.ts +0 -34
  43. package/src/lib/config/config.interface.ts +0 -9
  44. package/src/lib/config/define-config.ts +0 -16
  45. package/src/lib/config/index.ts +0 -2
  46. package/src/lib/effects/AnimateOnScroll.ts +0 -391
  47. package/src/lib/effects/State.tsx +0 -90
  48. package/src/lib/effects/SyncedFixedWrapper.tsx +0 -62
  49. package/src/lib/effects/ThemeProvider.tsx +0 -174
  50. package/src/lib/effects/block-scroll.effect.tsx +0 -313
  51. package/src/lib/effects/custom-scroll/custom-scroll.effect.tsx +0 -407
  52. package/src/lib/effects/custom-scroll/custom-scroll.interface.ts +0 -29
  53. package/src/lib/effects/custom-scroll/custom-scroll.style.ts +0 -32
  54. package/src/lib/effects/custom-scroll/index.ts +0 -3
  55. package/src/lib/effects/index.ts +0 -7
  56. package/src/lib/effects/ripple/RippleEffect.tsx +0 -116
  57. package/src/lib/effects/ripple/index.tsx +0 -1
  58. package/src/lib/effects/scrollDriven.ts +0 -239
  59. package/src/lib/effects/smooth-scroll.effect.tsx +0 -112
  60. package/src/lib/effects/theme.worker.ts +0 -97
  61. package/src/lib/hooks/index.ts +0 -10
  62. package/src/lib/hooks/useTooltipTrigger.ts +0 -270
  63. package/src/lib/icon/icon.tsx +0 -125
  64. package/src/lib/icon/index.ts +0 -1
  65. package/src/lib/index.ts +0 -8
  66. package/src/lib/interfaces/button.interface.ts +0 -65
  67. package/src/lib/interfaces/card.interface.ts +0 -11
  68. package/src/lib/interfaces/carousel-item.interface.ts +0 -12
  69. package/src/lib/interfaces/carousel.interface.ts +0 -41
  70. package/src/lib/interfaces/checkbox.interface.ts +0 -39
  71. package/src/lib/interfaces/chip.interface.ts +0 -97
  72. package/src/lib/interfaces/chips.interface.ts +0 -37
  73. package/src/lib/interfaces/date-picker.interface.ts +0 -79
  74. package/src/lib/interfaces/divider.interface.ts +0 -7
  75. package/src/lib/interfaces/fab-menu.interface.ts +0 -12
  76. package/src/lib/interfaces/fab.interface.ts +0 -27
  77. package/src/lib/interfaces/icon-button.interface.ts +0 -38
  78. package/src/lib/interfaces/index.ts +0 -26
  79. package/src/lib/interfaces/menu-group.interface.ts +0 -13
  80. package/src/lib/interfaces/menu-item.interface.ts +0 -29
  81. package/src/lib/interfaces/menu.interface.ts +0 -19
  82. package/src/lib/interfaces/navigation-rail-item.interface.ts +0 -39
  83. package/src/lib/interfaces/navigation-rail.interface.ts +0 -39
  84. package/src/lib/interfaces/progress-indicator.interface.ts +0 -41
  85. package/src/lib/interfaces/side-sheet.interface.tsx +0 -28
  86. package/src/lib/interfaces/slider.interface.ts +0 -27
  87. package/src/lib/interfaces/snackbar.interface.ts +0 -13
  88. package/src/lib/interfaces/switch.interface.ts +0 -14
  89. package/src/lib/interfaces/tab-group.interface.ts +0 -13
  90. package/src/lib/interfaces/tab-panels.interface.ts +0 -21
  91. package/src/lib/interfaces/tab.interface.ts +0 -31
  92. package/src/lib/interfaces/tabs.interface.ts +0 -22
  93. package/src/lib/interfaces/text-field.interface.ts +0 -61
  94. package/src/lib/interfaces/tooltip.interface.ts +0 -61
  95. package/src/lib/styles/button.style.ts +0 -136
  96. package/src/lib/styles/card.style.ts +0 -29
  97. package/src/lib/styles/carousel-item.style.ts +0 -24
  98. package/src/lib/styles/carousel.style.ts +0 -22
  99. package/src/lib/styles/checkbox.style.ts +0 -64
  100. package/src/lib/styles/chip.style.ts +0 -62
  101. package/src/lib/styles/chips.style.ts +0 -20
  102. package/src/lib/styles/date-picker.style.ts +0 -43
  103. package/src/lib/styles/divider.style.ts +0 -31
  104. package/src/lib/styles/fab-menu.style.ts +0 -29
  105. package/src/lib/styles/fab.style.ts +0 -49
  106. package/src/lib/styles/icon-button.style.ts +0 -168
  107. package/src/lib/styles/index.ts +0 -25
  108. package/src/lib/styles/menu-group.style.ts +0 -34
  109. package/src/lib/styles/menu-headline.style.ts +0 -20
  110. package/src/lib/styles/menu-item.style.ts +0 -45
  111. package/src/lib/styles/menu.style.ts +0 -32
  112. package/src/lib/styles/navigation-rail-item.style.ts +0 -56
  113. package/src/lib/styles/navigation-rail.style.ts +0 -36
  114. package/src/lib/styles/progress-indicator.style.ts +0 -72
  115. package/src/lib/styles/side-sheet.style.ts +0 -45
  116. package/src/lib/styles/slider.style.ts +0 -41
  117. package/src/lib/styles/snackbar.style.ts +0 -26
  118. package/src/lib/styles/switch.style.ts +0 -67
  119. package/src/lib/styles/tab-panels.style.ts +0 -35
  120. package/src/lib/styles/tab.style.ts +0 -78
  121. package/src/lib/styles/tabs.style.ts +0 -22
  122. package/src/lib/styles/text-field.style.ts +0 -115
  123. package/src/lib/styles/tooltip.style.ts +0 -48
  124. package/src/lib/utils/component-helper.ts +0 -134
  125. package/src/lib/utils/component.ts +0 -34
  126. package/src/lib/utils/index.ts +0 -7
  127. package/src/lib/utils/string.ts +0 -9
  128. package/src/lib/utils/styles/classnames.ts +0 -49
  129. package/src/lib/utils/styles/get-classname.ts +0 -96
  130. package/src/lib/utils/styles/index.ts +0 -4
  131. package/src/lib/utils/styles/use-classnames.ts +0 -25
  132. package/src/stories/action/button.stories.tsx +0 -86
  133. package/src/stories/action/fab.stories.tsx +0 -54
  134. package/src/stories/action/icon-button.stories.tsx +0 -134
  135. package/src/stories/assets/accessibility.png +0 -0
  136. package/src/stories/assets/accessibility.svg +0 -5
  137. package/src/stories/assets/addon-library.png +0 -0
  138. package/src/stories/assets/assets.png +0 -0
  139. package/src/stories/assets/context.png +0 -0
  140. package/src/stories/assets/discord.svg +0 -15
  141. package/src/stories/assets/docs.png +0 -0
  142. package/src/stories/assets/figma-plugin.png +0 -0
  143. package/src/stories/assets/github.svg +0 -3
  144. package/src/stories/assets/share.png +0 -0
  145. package/src/stories/assets/styling.png +0 -0
  146. package/src/stories/assets/testing.png +0 -0
  147. package/src/stories/assets/theming.png +0 -0
  148. package/src/stories/assets/tutorials.svg +0 -12
  149. package/src/stories/assets/youtube.svg +0 -4
  150. package/src/stories/communication/ProgressIndicator.stories.tsx +0 -57
  151. package/src/stories/communication/SnackBar.stories.tsx +0 -32
  152. package/src/stories/communication/tool-tip.stories.tsx +0 -133
  153. package/src/stories/containment/card.stories.tsx +0 -42
  154. package/src/stories/containment/carousel.stories.tsx +0 -65
  155. package/src/stories/containment/divider.stories.tsx +0 -35
  156. package/src/stories/containment/slide-sheet.stories.tsx +0 -45
  157. package/src/stories/effect/smooth-scroll.stories.tsx +0 -54
  158. package/src/stories/navigation/navigation-rail/navigation-rail-item.stories.tsx +0 -65
  159. package/src/stories/navigation/navigation-rail/navigation-rail.stories.tsx +0 -122
  160. package/src/stories/navigation/tabs/tab.stories.tsx +0 -57
  161. package/src/stories/navigation/tabs/tabs.stories.tsx +0 -102
  162. package/src/stories/selection/slider.stories.tsx +0 -85
  163. package/src/stories/selection/switch.stories.tsx +0 -46
  164. package/src/stories/text-inputs/text-field.stories.tsx +0 -135
  165. package/src/tests/Button.spec.tsx +0 -67
  166. package/src/tests/useClassNames.spec.tsx +0 -82
  167. package/src/udixio.css +0 -120
  168. package/theme.config.ts +0 -7
  169. package/tsconfig.json +0 -16
  170. package/tsconfig.lib.json +0 -51
  171. package/tsconfig.spec.json +0 -37
  172. package/tsconfig.storybook.json +0 -38
  173. package/vite.config.ts +0 -96
@@ -1,109 +0,0 @@
1
- import React, { useEffect, useRef, useState } from 'react';
2
- import { AnchorPositioner } from './AnchorPositioner';
3
- import { Menu } from './Menu';
4
- // import { MenuProps } from '../interfaces/menu.interface'; // MenuProps is not exported from interface file usually, check file content
5
- import { MenuInterface } from '../interfaces';
6
- import { ReactProps } from '../utils';
7
-
8
- // MenuInterface has props: MenuProps.
9
- // But MenuProps might not be exported directly from the package index, so accessing it via MenuInterface['props'] is safer if we can't import it.
10
- // Actually checking Step 1271, MenuProps IS exported.
11
-
12
- export type ContextMenuProps = {
13
- props: { trigger: React.ReactNode } & MenuInterface['props'];
14
- type: 'div';
15
- states: {
16
- hasGroups: boolean;
17
- };
18
- elements: [''];
19
- };
20
-
21
- export const ContextMenu = ({
22
- trigger,
23
- children,
24
- ...menuProps
25
- }: ReactProps<ContextMenuProps>) => {
26
- const [contextMenu, setContextMenu] = useState<{
27
- mouseX: number;
28
- mouseY: number;
29
- } | null>(null);
30
- const anchorRef = useRef<HTMLDivElement>(null);
31
-
32
- const handleContextMenu = (event: React.MouseEvent) => {
33
- event.preventDefault();
34
- setContextMenu({
35
- mouseX: event.clientX,
36
- mouseY: event.clientY,
37
- });
38
- };
39
-
40
- const handleClose = () => {
41
- setContextMenu(null);
42
- };
43
-
44
- const handleSelect = () => {
45
- handleClose();
46
- };
47
-
48
- useEffect(() => {
49
- if (!contextMenu) return;
50
- const handleOutsideInteraction = () => setContextMenu(null);
51
- window.addEventListener('click', handleOutsideInteraction);
52
- window.addEventListener('scroll', handleOutsideInteraction, true);
53
-
54
- return () => {
55
- window.removeEventListener('click', handleOutsideInteraction);
56
- window.removeEventListener('scroll', handleOutsideInteraction, true);
57
- };
58
- }, [contextMenu]);
59
-
60
- // Clone trigger if valid element to attach onContextMenu, otherwise wrap
61
- const triggerElement = React.isValidElement(trigger) ? (
62
- React.cloneElement(
63
- trigger as React.ReactElement,
64
- {
65
- onContextMenu: (e: React.MouseEvent) => {
66
- handleContextMenu(e);
67
- // Call original handler if exists
68
- (trigger as React.ReactElement).props.onContextMenu?.(e);
69
- },
70
- } as any,
71
- )
72
- ) : (
73
- <div onContextMenu={handleContextMenu} className="inline-block">
74
- {trigger}
75
- </div>
76
- );
77
-
78
- return (
79
- <>
80
- {triggerElement}
81
-
82
- {/* Invisible anchor element positioned at cursor */}
83
- <div
84
- ref={anchorRef}
85
- style={{
86
- position: 'fixed',
87
- top: contextMenu?.mouseY ?? 0,
88
- left: contextMenu?.mouseX ?? 0,
89
- width: 1,
90
- height: 1,
91
- pointerEvents: 'none',
92
- visibility: 'hidden',
93
- }}
94
- />
95
-
96
- {contextMenu && (
97
- <AnchorPositioner
98
- anchorRef={anchorRef}
99
- position="bottom right"
100
- onClick={(e) => e.stopPropagation()}
101
- >
102
- <Menu onClick={handleSelect} {...menuProps}>
103
- {children}
104
- </Menu>
105
- </AnchorPositioner>
106
- )}
107
- </>
108
- );
109
- };
@@ -1,432 +0,0 @@
1
- import { useEffect, useMemo, useRef, useState } from 'react';
2
- import { useDatePickerStyle } from '../styles/date-picker.style';
3
- import { classNames, ReactProps } from '../utils';
4
- import {
5
- DatePickerInterface,
6
- DateRange,
7
- } from '../interfaces/date-picker.interface';
8
- import {
9
- faChevronDown,
10
- faChevronLeft,
11
- faChevronRight,
12
- } from '@fortawesome/free-solid-svg-icons';
13
- import { Button } from './Button';
14
- import { IconButton } from './IconButton';
15
- import { AnimatePresence, motion } from 'motion/react';
16
- import { Icon } from '../icon';
17
-
18
- /**
19
- * DatePickers let users select a date, or a range of dates.
20
- * @status beta
21
- * @category Selection
22
- */
23
- export const DatePicker = ({
24
- value: valueProp,
25
- defaultValue,
26
- onChange,
27
- minDate,
28
- maxDate,
29
- shouldDisableDate,
30
- locale = 'default',
31
- weekStartDay = 0,
32
- className,
33
- style,
34
- mode = 'single',
35
- ...restProps
36
- }: ReactProps<DatePickerInterface>) => {
37
- // State for the currently displayed month (always set to the 1st of the month)
38
- const [viewDate, setViewDate] = useState(() => {
39
- // Try to find a valid start date from value to focus
40
- const extractDate = (v: any): Date | null => {
41
- if (v instanceof Date) return v;
42
- if (Array.isArray(v) && v[0]) return v[0];
43
- return null;
44
- };
45
- const start =
46
- extractDate(valueProp) || extractDate(defaultValue) || new Date();
47
- return new Date(start.getFullYear(), start.getMonth(), 1);
48
- });
49
-
50
- const [direction, setDirection] = useState(0);
51
- const [viewMode, setViewMode] = useState<'day' | 'year'>('day');
52
-
53
- // State for selected date
54
- const isControlled = valueProp !== undefined;
55
- const [internalValue, setInternalValue] = useState<Date | DateRange | null>(
56
- defaultValue || null,
57
- );
58
- const selectedValue = isControlled ? valueProp || null : internalValue;
59
-
60
- // Calendar generation logic
61
- const daysInMonth = (year: number, month: number) =>
62
- new Date(year, month + 1, 0).getDate();
63
-
64
- const calendarDays = useMemo(() => {
65
- const year = viewDate.getFullYear();
66
- const month = viewDate.getMonth();
67
- const daysCount = daysInMonth(year, month);
68
- const startDay = new Date(year, month, 1).getDay(); // 0=Sun (Fixed JS getDay)
69
-
70
- // Adjust start index based on weekStartDay
71
- // shift: logic to map standard JS Day (0=Sun) to our week start
72
- // If weekStart=1 (Mon): Sun(0) -> 6, Mon(1) -> 0, Tue(2) -> 1
73
- const startIndex = (startDay - weekStartDay + 7) % 7;
74
-
75
- const days: Array<{ date: Date; isCurrentMonth: boolean }> = [];
76
-
77
- // Prev month
78
- const prevMonthDaysCount = daysInMonth(year, month - 1);
79
- for (let i = startIndex - 1; i >= 0; i--) {
80
- days.push({
81
- date: new Date(year, month - 1, prevMonthDaysCount - i),
82
- isCurrentMonth: false,
83
- });
84
- }
85
-
86
- // Current month
87
- for (let i = 1; i <= daysCount; i++) {
88
- days.push({ date: new Date(year, month, i), isCurrentMonth: true });
89
- }
90
-
91
- // Next month padding - Ensure always 42 days (6 rows) for fixed height animation
92
- const currentLen = days.length;
93
- const remaining = 42 - currentLen;
94
- for (let i = 1; i <= remaining; i++) {
95
- days.push({
96
- date: new Date(year, month + 1, i),
97
- isCurrentMonth: false,
98
- });
99
- }
100
-
101
- return days;
102
- }, [viewDate, weekStartDay]);
103
-
104
- const years = useMemo(() => {
105
- const currentYear = new Date().getFullYear();
106
- const start = currentYear - 100;
107
- const end = currentYear + 100;
108
- const list = [];
109
- for (let i = start; i <= end; i++) {
110
- list.push(i);
111
- }
112
- return list;
113
- }, []);
114
-
115
- const yearsContainerRef = useRef<HTMLDivElement>(null);
116
-
117
- // Scroll to selected year when opening year view
118
- useEffect(() => {
119
- if (viewMode === 'year' && yearsContainerRef.current) {
120
- const selectedYearBtn = yearsContainerRef.current.querySelector(
121
- '[data-selected="true"]',
122
- );
123
- if (selectedYearBtn) {
124
- selectedYearBtn.scrollIntoView({ block: 'center' });
125
- }
126
- }
127
- }, [viewMode]);
128
-
129
- // Formatters
130
- const monthFormatter = useMemo(
131
- () => new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }),
132
- [locale],
133
- );
134
- const weekDayFormatter = useMemo(
135
- () => new Intl.DateTimeFormat(locale, { weekday: 'narrow' }),
136
- [locale],
137
- );
138
-
139
- const weekDays = useMemo(() => {
140
- const baseDate = new Date(2023, 0, 1 + weekStartDay); // Jan 1 2023 was Sun. Jan (1+1)=2 is Mon.
141
- return Array.from({ length: 7 }).map((_, i) => {
142
- const d = new Date(baseDate);
143
- d.setDate(baseDate.getDate() + i);
144
- return weekDayFormatter.format(d).charAt(0).toUpperCase();
145
- });
146
- }, [weekDayFormatter, weekStartDay]);
147
-
148
- // Handlers
149
- const handlePrevMonth = () => {
150
- setDirection(-1);
151
- setViewDate((d) => new Date(d.getFullYear(), d.getMonth() - 1, 1));
152
- };
153
- const handleNextMonth = () => {
154
- setDirection(1);
155
- setViewDate((d) => new Date(d.getFullYear(), d.getMonth() + 1, 1));
156
- };
157
-
158
- const handleYearSelect = (year: number) => {
159
- setViewDate((d) => new Date(year, d.getMonth(), 1));
160
- setViewMode('day');
161
- };
162
-
163
- const isSameDay = (d1: Date | null | undefined, d2: Date) => {
164
- if (!d1) return false;
165
- return (
166
- d1.getDate() === d2.getDate() &&
167
- d1.getMonth() === d2.getMonth() &&
168
- d1.getFullYear() === d2.getFullYear()
169
- );
170
- };
171
-
172
- const isToday = (date: Date) => isSameDay(new Date(), date);
173
-
174
- const handleDateClick = (date: Date) => {
175
- let newValue: Date | DateRange | null = date;
176
-
177
- if (mode === 'single') {
178
- newValue = date;
179
- // Single mode always sets date
180
- } else {
181
- // Range mode
182
- const current = selectedValue as DateRange | null;
183
- const [start, end] = Array.isArray(current) ? current : [null, null];
184
-
185
- if (!start || (start && end)) {
186
- // Start new range (if was simple date or full range)
187
- newValue = [date, null];
188
- } else {
189
- // Complete range
190
- if (date < start) {
191
- newValue = [date, start];
192
- } else {
193
- newValue = [start, date];
194
- }
195
- }
196
- }
197
-
198
- if (!isControlled) {
199
- setInternalValue(newValue);
200
- }
201
- if (onChange) {
202
- onChange(newValue);
203
- }
204
- };
205
-
206
- const checkSelection = (date: Date) => {
207
- if (mode === 'single') {
208
- return {
209
- isSelected: isSameDay(selectedValue as Date, date),
210
- isStart: false,
211
- isEnd: false,
212
- isInRange: false,
213
- };
214
- }
215
- const safeRange = Array.isArray(selectedValue)
216
- ? selectedValue
217
- : [selectedValue, null];
218
- const [start, end] = safeRange as DateRange;
219
- const isStart = isSameDay(start, date);
220
- const isEnd = isSameDay(end, date);
221
-
222
- // Check range
223
- let isInRange = false;
224
- if (start && end) {
225
- // Simple range check (ignore time components for safety)
226
- // Normalize to midnight for strict day comparison
227
- const s = new Date(
228
- start.getFullYear(),
229
- start.getMonth(),
230
- start.getDate(),
231
- ).getTime();
232
- const e = new Date(
233
- end.getFullYear(),
234
- end.getMonth(),
235
- end.getDate(),
236
- ).getTime();
237
- const d = new Date(
238
- date.getFullYear(),
239
- date.getMonth(),
240
- date.getDate(),
241
- ).getTime();
242
- isInRange = d > s && d < e;
243
- }
244
-
245
- return { isSelected: isStart || isEnd, isStart, isEnd, isInRange };
246
- };
247
-
248
- const styles = useDatePickerStyle({
249
- hasSelected: !!selectedValue,
250
- });
251
-
252
- const variants = {
253
- enter: (direction: number) => ({
254
- x: direction > 0 ? '100%' : '-100%',
255
- opacity: 0,
256
- }),
257
- center: {
258
- x: 0,
259
- opacity: 1,
260
- },
261
- exit: (direction: number) => ({
262
- x: direction < 0 ? '100%' : '-100%',
263
- opacity: 0,
264
- }),
265
- };
266
-
267
- return (
268
- <div
269
- className={classNames(styles.datePicker, className)}
270
- style={style}
271
- {...(restProps as any)}
272
- >
273
- {/* Header */}
274
- <div className={styles.header}>
275
- <Button
276
- variant="text"
277
- disableTextMargins
278
- size="small"
279
- onClick={() => setViewMode((m) => (m === 'day' ? 'year' : 'day'))}
280
- className="text-label-large font-bold capitalize text-on-surface hover:bg-surface-container-highest"
281
- >
282
- <span className="mr-2">
283
- {viewMode === 'day'
284
- ? monthFormatter.format(viewDate)
285
- : viewDate.getFullYear()}
286
- </span>
287
- <Icon
288
- icon={faChevronDown}
289
- className={classNames(
290
- 'w-3 h-3 transition-transform duration-200 inline',
291
- viewMode === 'year' && 'rotate-180',
292
- )}
293
- />
294
- </Button>
295
-
296
- {viewMode === 'day' && (
297
- <div className="flex items-center">
298
- <IconButton
299
- size={'xSmall'}
300
- allowShapeTransformation={false}
301
- onClick={handlePrevMonth}
302
- icon={faChevronLeft}
303
- label="Previous month"
304
- title={null}
305
- />
306
- <IconButton
307
- size={'xSmall'}
308
- allowShapeTransformation={false}
309
- onClick={handleNextMonth}
310
- icon={faChevronRight}
311
- label="Next month"
312
- title={null}
313
- />
314
- </div>
315
- )}
316
- </div>
317
-
318
- {viewMode === 'year' ? (
319
- <div
320
- className="h-[280px] overflow-y-auto grid grid-cols-3 gap-2 p-2 scrollbar-hide"
321
- ref={yearsContainerRef}
322
- >
323
- {years.map((year) => (
324
- <Button
325
- size={'small'}
326
- key={year}
327
- variant={year === viewDate.getFullYear() ? 'filled' : 'text'}
328
- onClick={() => handleYearSelect(year)}
329
- data-selected={year === viewDate.getFullYear()}
330
- className={classNames('w-full', {
331
- 'text-on-surface': year !== viewDate.getFullYear(),
332
- })}
333
- label={year.toString()}
334
- >
335
- {year}
336
- </Button>
337
- ))}
338
- </div>
339
- ) : (
340
- <>
341
- {/* Week Days */}
342
- <div className={styles.weekDays}>
343
- {weekDays.map((day, i) => (
344
- <div key={i} className={styles.weekDay}>
345
- {day}
346
- </div>
347
- ))}
348
- </div>
349
-
350
- {/* Days Grid */}
351
- <div className="overflow-hidden relative min-h-[240px]">
352
- <AnimatePresence
353
- mode="popLayout"
354
- initial={false}
355
- custom={direction}
356
- >
357
- <motion.div
358
- key={viewDate.toISOString()}
359
- custom={direction}
360
- variants={variants}
361
- initial="enter"
362
- animate="center"
363
- exit="exit"
364
- transition={{ type: 'spring', bounce: 0, duration: 0.3 }}
365
- className={styles.daysGrid}
366
- >
367
- {calendarDays.map((item, index) => {
368
- if (!item.isCurrentMonth) {
369
- return <div key={index} className={styles.dayCell} />;
370
- }
371
-
372
- const { isSelected, isStart, isEnd, isInRange } =
373
- checkSelection(item.date);
374
- const isTodayDate = isToday(item.date);
375
- const isDisabled =
376
- (minDate && item.date < minDate) ||
377
- (maxDate && item.date > maxDate) ||
378
- shouldDisableDate?.(item.date);
379
-
380
- return (
381
- <div
382
- key={index}
383
- className={classNames(
384
- styles.dayCell,
385
- // Range background styles applied to the cell wrapper
386
- isInRange && 'bg-primary/20',
387
- isStart &&
388
- (selectedValue as DateRange)?.[1] &&
389
- 'bg-gradient-to-r from-transparent to-primary/20',
390
- isEnd &&
391
- (selectedValue as DateRange)?.[0] &&
392
- 'bg-gradient-to-l from-transparent to-primary/20',
393
- )}
394
- >
395
- <Button
396
- className={() => ({
397
- button: classNames('aspect-square h-[40px] p-0', {
398
- 'text-on-surface': !isSelected && !isTodayDate,
399
- 'opacity-50': isDisabled,
400
- }),
401
- stateLayer: classNames({
402
- '!bg-transparent': isDisabled,
403
- }),
404
- })}
405
- size="small"
406
- allowShapeTransformation={false}
407
- variant={
408
- classNames({
409
- filled: isSelected,
410
- outlined: isTodayDate,
411
- text: !isSelected && !isTodayDate,
412
- }) as any
413
- }
414
- label={item.date.getDate().toString()}
415
- onClick={() => handleDateClick(item.date)}
416
- disabled={isDisabled}
417
- >
418
- {item.date.getDate().toString()}
419
- </Button>
420
- </div>
421
- );
422
- })}
423
- </motion.div>
424
- </AnimatePresence>
425
- </div>
426
- </>
427
- )}
428
- </div>
429
- );
430
- };
431
-
432
- // Helper for generic check - removed unused
@@ -1,20 +0,0 @@
1
- import { useDividerStyle } from '../styles';
2
- import { DividerInterface } from '../interfaces';
3
- import { ReactProps } from '../utils';
4
-
5
- /**
6
- * Dividers are thin lines that group content in lists or other containers
7
- * @status beta
8
- * @category Layout
9
- * @devx
10
- * - Renders a semantic `<hr>`; use `orientation` for vertical dividers.
11
- */
12
- export const Divider = ({
13
- orientation = 'horizontal',
14
- className,
15
- ...restProps
16
- }: ReactProps<DividerInterface>) => {
17
- const styles = useDividerStyle({ orientation, className });
18
-
19
- return <hr className={styles.divider} {...restProps} />;
20
- };
@@ -1,127 +0,0 @@
1
- import React, { useRef } from 'react';
2
- import { Icon } from '../icon';
3
- import { AnimatePresence, motion } from 'motion/react';
4
- import { FabInterface } from '../interfaces/fab.interface';
5
- import { useFabStyle } from '../styles/fab.style';
6
- import { classNames } from '../utils';
7
- import { ReactProps } from '../utils/component';
8
- import { Tooltip } from './Tooltip';
9
- import { State } from '../effects';
10
-
11
- /**
12
- * Floating action buttons (FABs) help people take primary actions
13
- * @status beta
14
- * @category Action
15
- * @devx
16
- * - Requires `label` or children; icon-only still needs a label for a11y.
17
- * @limitations
18
- * - No built-in positioning; placement is handled by the layout.
19
- */
20
- export const Fab = ({
21
- className,
22
- label,
23
- variant = 'primary',
24
- size = 'medium',
25
- href,
26
- type,
27
- icon,
28
- extended = false,
29
- ref,
30
- transition,
31
- children,
32
- ...restProps
33
- }: ReactProps<FabInterface>) => {
34
- if (children) label = children;
35
- if (!label) {
36
- throw new Error(
37
- 'FAB component requires either a label prop or children content',
38
- );
39
- }
40
- const ElementType = href ? 'a' : 'button';
41
-
42
- const styles = useFabStyle({
43
- href,
44
- icon,
45
- extended,
46
- label,
47
- size,
48
- variant,
49
- className,
50
- transition,
51
- children: label,
52
- });
53
-
54
- transition = { duration: 0.3, ...transition };
55
-
56
- const defaultRef = useRef(null);
57
- const resolvedRef = ref || defaultRef;
58
-
59
- const labelVariants = {
60
- visible: {
61
- width: 'auto',
62
- marginLeft: 12,
63
- opacity: 1,
64
- transition: {
65
- ...transition,
66
- opacity: {
67
- duration: transition.duration! / 2,
68
- delay: transition.duration! - transition.duration! / 2,
69
- },
70
- },
71
- },
72
- hidden: {
73
- width: 0,
74
- marginLeft: 0,
75
- opacity: 0,
76
- transition: {
77
- ...transition,
78
- marginLeft: {
79
- duration: transition.duration! / 2,
80
- delay: transition.duration! - transition.duration! / 2,
81
- },
82
- },
83
- },
84
- };
85
- return (
86
- <ElementType
87
- {...(restProps as any)}
88
- ref={resolvedRef}
89
- href={href}
90
- aria-label={extended ? undefined : label}
91
- className={styles.fab}
92
- >
93
- <Tooltip
94
- trigger={extended ? null : undefined}
95
- text={label}
96
- targetRef={resolvedRef}
97
- />
98
- <State
99
- style={{ transition: transition.duration + 's' }}
100
- className={styles.stateLayer}
101
- colorName={classNames({
102
- 'on-primary': variant == 'primary',
103
- 'on-secondary': variant == 'secondary',
104
- 'on-tertiary': variant == 'tertiary',
105
- 'on-primary-container': variant == 'primaryContainer',
106
- 'on-secondary-container': variant == 'secondaryContainer',
107
- 'on-tertiary-container': variant == 'tertiaryContainer',
108
- })}
109
- stateClassName={'state-ripple-group-[fab]'}
110
- />
111
- <Icon icon={icon} className={styles.icon} />
112
- <AnimatePresence>
113
- {extended && (
114
- <motion.span
115
- variants={labelVariants}
116
- initial="hidden"
117
- animate="visible"
118
- exit="hidden"
119
- className={styles.label}
120
- >
121
- {label}
122
- </motion.span>
123
- )}
124
- </AnimatePresence>
125
- </ElementType>
126
- );
127
- };