@g4rcez/components 3.0.0-0 → 3.0.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.
- package/dist/ai/SKILL.md +266 -0
- package/dist/ai/docs/Alert.md +167 -0
- package/dist/ai/docs/AnimatedList.md +205 -0
- package/dist/ai/docs/Autocomplete.md +225 -0
- package/dist/ai/docs/Button.md +182 -0
- package/dist/ai/docs/Calendar.md +219 -0
- package/dist/ai/docs/Card.md +174 -0
- package/dist/ai/docs/Checkbox.md +199 -0
- package/dist/ai/docs/CommandPalette.md +293 -0
- package/dist/ai/docs/DatePicker.md +171 -0
- package/dist/ai/docs/Dropdown.md +223 -0
- package/dist/ai/docs/Empty.md +163 -0
- package/dist/ai/docs/Expand.md +143 -0
- package/dist/ai/docs/FileUpload.md +225 -0
- package/dist/ai/docs/Form.md +107 -0
- package/dist/ai/docs/FormReset.md +117 -0
- package/dist/ai/docs/Heading.md +88 -0
- package/dist/ai/docs/Input.md +237 -0
- package/dist/ai/docs/InputField.md +170 -0
- package/dist/ai/docs/List.md +205 -0
- package/dist/ai/docs/Menu.md +166 -0
- package/dist/ai/docs/Modal.md +280 -0
- package/dist/ai/docs/MultiSelect.md +196 -0
- package/dist/ai/docs/Notifications.md +231 -0
- package/dist/ai/docs/PageCalendar.md +271 -0
- package/dist/ai/docs/Polymorph.md +159 -0
- package/dist/ai/docs/Progress.md +145 -0
- package/dist/ai/docs/Radiobox.md +128 -0
- package/dist/ai/docs/RenderOnView.md +138 -0
- package/dist/ai/docs/Resizable.md +159 -0
- package/dist/ai/docs/Select.md +284 -0
- package/dist/ai/docs/Shortcut.md +105 -0
- package/dist/ai/docs/Skeleton.md +166 -0
- package/dist/ai/docs/Slider.md +144 -0
- package/dist/ai/docs/Slot.md +173 -0
- package/dist/ai/docs/Spinner.md +118 -0
- package/dist/ai/docs/Stats.md +137 -0
- package/dist/ai/docs/Step.md +159 -0
- package/dist/ai/docs/Switch.md +167 -0
- package/dist/ai/docs/Table.md +298 -0
- package/dist/ai/docs/Tabs.md +191 -0
- package/dist/ai/docs/Tag.md +224 -0
- package/dist/ai/docs/TaskList.md +144 -0
- package/dist/ai/docs/Textarea.md +167 -0
- package/dist/ai/docs/Timeline.md +210 -0
- package/dist/ai/docs/Toolbar.md +132 -0
- package/dist/ai/docs/Tooltip.md +231 -0
- package/dist/ai/docs/TransferList.md +142 -0
- package/dist/ai/docs/Typography.md +187 -0
- package/dist/ai/docs/Wizard.md +213 -0
- package/dist/ai/docs/index.md +183 -0
- package/dist/components/core/button.d.ts +2 -8
- package/dist/components/core/button.d.ts.map +1 -1
- package/dist/components/core/polymorph.d.ts.map +1 -1
- package/dist/components/core/slot.d.ts +1 -1
- package/dist/components/core/slot.d.ts.map +1 -1
- package/dist/components/core/tag.d.ts +2 -2
- package/dist/components/core/tag.d.ts.map +1 -1
- package/dist/components/core/typography.d.ts.map +1 -1
- package/dist/components/display/alert.d.ts.map +1 -1
- package/dist/components/display/calendar.d.ts.map +1 -1
- package/dist/components/display/card.d.ts.map +1 -1
- package/dist/components/display/list.d.ts.map +1 -1
- package/dist/components/display/notifications.d.ts +2 -0
- package/dist/components/display/notifications.d.ts.map +1 -1
- package/dist/components/display/progress.d.ts.map +1 -1
- package/dist/components/display/skeleton.d.ts.map +1 -1
- package/dist/components/display/step.d.ts.map +1 -1
- package/dist/components/display/tabs.d.ts.map +1 -1
- package/dist/components/floating/command-palette.d.ts +1 -0
- package/dist/components/floating/command-palette.d.ts.map +1 -1
- package/dist/components/floating/dropdown.d.ts +1 -0
- package/dist/components/floating/dropdown.d.ts.map +1 -1
- package/dist/components/floating/menu.d.ts +2 -2
- package/dist/components/floating/menu.d.ts.map +1 -1
- package/dist/components/floating/modal.d.ts +20 -53
- package/dist/components/floating/modal.d.ts.map +1 -1
- package/dist/components/floating/tooltip.d.ts.map +1 -1
- package/dist/components/floating/wizard.d.ts +1 -1
- package/dist/components/floating/wizard.d.ts.map +1 -1
- package/dist/components/form/autocomplete.d.ts.map +1 -1
- package/dist/components/form/date-picker.d.ts.map +1 -1
- package/dist/components/form/free-text.d.ts.map +1 -1
- package/dist/components/form/input-field.d.ts +3 -2
- package/dist/components/form/input-field.d.ts.map +1 -1
- package/dist/components/form/multi-select.d.ts.map +1 -1
- package/dist/components/form/select.d.ts.map +1 -1
- package/dist/components/form/slider.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/page-calendar/calendar-header.d.ts +16 -0
- package/dist/components/page-calendar/calendar-header.d.ts.map +1 -0
- package/dist/components/page-calendar/day-view.d.ts +12 -0
- package/dist/components/page-calendar/day-view.d.ts.map +1 -0
- package/dist/components/page-calendar/event-pill.d.ts +9 -0
- package/dist/components/page-calendar/event-pill.d.ts.map +1 -0
- package/dist/components/page-calendar/index.d.ts +4 -0
- package/dist/components/page-calendar/index.d.ts.map +1 -0
- package/dist/components/page-calendar/month-view.d.ts +11 -0
- package/dist/components/page-calendar/month-view.d.ts.map +1 -0
- package/dist/components/page-calendar/page-calendar.d.ts +18 -0
- package/dist/components/page-calendar/page-calendar.d.ts.map +1 -0
- package/dist/components/page-calendar/page-calendar.types.d.ts +18 -0
- package/dist/components/page-calendar/page-calendar.types.d.ts.map +1 -0
- package/dist/components/page-calendar/page-calendar.utils.d.ts +18 -0
- package/dist/components/page-calendar/page-calendar.utils.d.ts.map +1 -0
- package/dist/components/page-calendar/week-view.d.ts +11 -0
- package/dist/components/page-calendar/week-view.d.ts.map +1 -0
- package/dist/components/table/index.d.ts.map +1 -1
- package/dist/components/table/inner-table.d.ts.map +1 -1
- package/dist/components/table/metadata.d.ts.map +1 -1
- package/dist/components/table/row.d.ts.map +1 -1
- package/dist/components/table/table-lib.d.ts.map +1 -1
- package/dist/components/table/thead.d.ts.map +1 -1
- package/dist/config/context.d.ts.map +1 -1
- package/dist/config/default-translations.d.ts +21 -4
- package/dist/config/default-translations.d.ts.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/hooks/use-components-provider.d.ts.map +1 -1
- package/dist/hooks/use-form.d.ts +11 -11
- package/dist/hooks/use-form.d.ts.map +1 -1
- package/dist/hooks/use-input-id.d.ts.map +1 -1
- package/dist/hooks/use-preferences.d.ts.map +1 -1
- package/dist/hooks/use-previous.d.ts.map +1 -1
- package/dist/hooks/use-reactive.d.ts.map +1 -1
- package/dist/hooks/use-resize-observer.d.ts.map +1 -1
- package/dist/hooks/use-stable-ref.d.ts.map +1 -1
- package/dist/hooks/use-swipe.d.ts.map +1 -1
- package/dist/hooks/use-translations.d.ts +21 -4
- package/dist/hooks/use-translations.d.ts.map +1 -1
- package/dist/index.css +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13862 -12512
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +24 -17
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/dom.d.ts +1 -0
- package/dist/lib/dom.d.ts.map +1 -1
- package/dist/lib/fns.d.ts.map +1 -1
- package/dist/preset/plugin.tailwind.d.ts +9 -0
- package/dist/preset/plugin.tailwind.d.ts.map +1 -0
- package/dist/preset/plugin.tailwind.js +27 -0
- package/dist/preset/preset.tailwind.d.ts +8 -0
- package/dist/preset/preset.tailwind.d.ts.map +1 -0
- package/dist/preset/preset.tailwind.js +54 -0
- package/dist/preset/src/styles/common.d.ts +2 -14
- package/dist/preset/src/styles/common.d.ts.map +1 -1
- package/dist/preset/src/styles/common.js +1 -0
- package/dist/preset/src/styles/dark.d.ts.map +1 -1
- package/dist/preset/src/styles/dark.js +119 -114
- package/dist/preset/src/styles/light.d.ts.map +1 -1
- package/dist/preset/src/styles/light.js +111 -106
- package/dist/preset/src/styles/theme.types.d.ts +17 -8
- package/dist/preset/src/styles/theme.types.d.ts.map +1 -1
- package/dist/styles/common.d.ts +2 -14
- package/dist/styles/common.d.ts.map +1 -1
- package/dist/styles/dark.d.ts.map +1 -1
- package/dist/styles/light.d.ts.map +1 -1
- package/dist/styles/theme.types.d.ts +17 -8
- package/dist/styles/theme.types.d.ts.map +1 -1
- package/package.json +299 -301
- package/dist/components/core/button.jsx +0 -86
- package/dist/components/core/heading.jsx +0 -4
- package/dist/components/core/polymorph.jsx +0 -5
- package/dist/components/core/render-on-view.jsx +0 -31
- package/dist/components/core/resizable.jsx +0 -51
- package/dist/components/core/slot.jsx +0 -163
- package/dist/components/core/tag.jsx +0 -51
- package/dist/components/core/typography.jsx +0 -26
- package/dist/components/display/alert.jsx +0 -56
- package/dist/components/display/calendar.jsx +0 -301
- package/dist/components/display/card.jsx +0 -43
- package/dist/components/display/empty.jsx +0 -11
- package/dist/components/display/list.jsx +0 -81
- package/dist/components/display/notifications.jsx +0 -98
- package/dist/components/display/progress.jsx +0 -13
- package/dist/components/display/shortcut.jsx +0 -23
- package/dist/components/display/skeleton.jsx +0 -14
- package/dist/components/display/spinner.jsx +0 -7
- package/dist/components/display/stats.jsx +0 -20
- package/dist/components/display/step.jsx +0 -131
- package/dist/components/display/tabs.jsx +0 -100
- package/dist/components/display/timeline.jsx +0 -25
- package/dist/components/floating/command-palette.jsx +0 -172
- package/dist/components/floating/dropdown.jsx +0 -53
- package/dist/components/floating/expand.jsx +0 -44
- package/dist/components/floating/menu.jsx +0 -147
- package/dist/components/floating/modal.jsx +0 -241
- package/dist/components/floating/toolbar.jsx +0 -5
- package/dist/components/floating/tooltip.jsx +0 -64
- package/dist/components/floating/wizard.jsx +0 -164
- package/dist/components/form/autocomplete.jsx +0 -275
- package/dist/components/form/checkbox.jsx +0 -12
- package/dist/components/form/date-picker.jsx +0 -115
- package/dist/components/form/file-upload.jsx +0 -133
- package/dist/components/form/form.jsx +0 -10
- package/dist/components/form/formReset.jsx +0 -17
- package/dist/components/form/free-text.jsx +0 -41
- package/dist/components/form/input-field.jsx +0 -54
- package/dist/components/form/input.jsx +0 -36
- package/dist/components/form/multi-select.jsx +0 -328
- package/dist/components/form/radiobox.jsx +0 -6
- package/dist/components/form/select.jsx +0 -42
- package/dist/components/form/slider.jsx +0 -45
- package/dist/components/form/switch.jsx +0 -46
- package/dist/components/form/task-list.jsx +0 -26
- package/dist/components/form/textarea.jsx +0 -12
- package/dist/components/form/transfer-list.jsx +0 -39
- package/dist/components/index.js +0 -43
- package/dist/components/table/filter.jsx +0 -141
- package/dist/components/table/group.jsx +0 -68
- package/dist/components/table/index.jsx +0 -60
- package/dist/components/table/inner-table.jsx +0 -104
- package/dist/components/table/metadata.jsx +0 -37
- package/dist/components/table/pagination.jsx +0 -73
- package/dist/components/table/row.jsx +0 -58
- package/dist/components/table/sort.jsx +0 -105
- package/dist/components/table/table-lib.js +0 -84
- package/dist/components/table/table.context.jsx +0 -4
- package/dist/components/table/thead.jsx +0 -103
- package/dist/config/context.js +0 -12
- package/dist/config/default-translations.jsx +0 -66
- package/dist/config/default-tweaks.js +0 -4
- package/dist/constants.js +0 -2
- package/dist/hooks/use-click-outside.js +0 -17
- package/dist/hooks/use-color-parser.js +0 -9
- package/dist/hooks/use-components-provider.jsx +0 -16
- package/dist/hooks/use-debounce.js +0 -12
- package/dist/hooks/use-floating-ref.js +0 -6
- package/dist/hooks/use-form.js +0 -549
- package/dist/hooks/use-hover.js +0 -18
- package/dist/hooks/use-input-id.js +0 -5
- package/dist/hooks/use-is-coarse-device.js +0 -12
- package/dist/hooks/use-locale.js +0 -10
- package/dist/hooks/use-media-query.js +0 -25
- package/dist/hooks/use-on-event.js +0 -7
- package/dist/hooks/use-parent.js +0 -21
- package/dist/hooks/use-preferences.js +0 -23
- package/dist/hooks/use-previous.js +0 -8
- package/dist/hooks/use-reactive.js +0 -8
- package/dist/hooks/use-remove-scroll.js +0 -61
- package/dist/hooks/use-resize-observer.js +0 -17
- package/dist/hooks/use-stable-ref.js +0 -8
- package/dist/hooks/use-swipe.js +0 -16
- package/dist/hooks/use-translations.js +0 -9
- package/dist/hooks/use-tweaks.js +0 -9
- package/dist/hooks/use-window-size.js +0 -14
- package/dist/lib/combi-keys.js +0 -60
- package/dist/lib/dict.js +0 -39
- package/dist/lib/dom.js +0 -44
- package/dist/lib/fns.js +0 -46
- package/dist/lib/fzf.js +0 -117
- package/dist/lib/keyboard-area.js +0 -14
- package/dist/preset/tailwindcssv4.d.ts +0 -3
- package/dist/preset/tailwindcssv4.d.ts.map +0 -1
- package/dist/preset/tailwindcssv4.js +0 -75
- package/dist/styles/common.js +0 -28
- package/dist/styles/dark.js +0 -209
- package/dist/styles/design-tokens.js +0 -69
- package/dist/styles/light.js +0 -209
- package/dist/styles/theme.js +0 -4
- package/dist/styles/theme.types.js +0 -1
- package/dist/types.js +0 -1
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { add, eachDayOfInterval, endOfWeek, isAfter, isBefore, isSameMonth, isToday, setYear, startOfDay, startOfMonth, startOfWeek, sub, format, set, } from "date-fns";
|
|
3
|
-
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
4
|
-
import { AnimatePresence, motion, MotionConfig } from "motion/react";
|
|
5
|
-
import React, { useEffect, useRef } from "react";
|
|
6
|
-
import { Is } from "sidekicker";
|
|
7
|
-
import TheMaskInput from "the-mask-input";
|
|
8
|
-
import { useReducer } from "use-typed-reducer";
|
|
9
|
-
import { useDebounce } from "../../hooks/use-debounce";
|
|
10
|
-
import { useLocale } from "../../hooks/use-locale";
|
|
11
|
-
import { useSwipe } from "../../hooks/use-swipe";
|
|
12
|
-
import { useTranslations } from "../../hooks/use-translations";
|
|
13
|
-
import { css } from "../../lib/dom";
|
|
14
|
-
import { splitInto, uuid } from "../../lib/fns";
|
|
15
|
-
import { Input } from "../form/input";
|
|
16
|
-
const timeRegex = /^(?<hour>\d\d):(?<min>\d\d)$/;
|
|
17
|
-
const transition = { type: "spring", bounce: 0.3, duration: 0.6 };
|
|
18
|
-
const dir = (mod) => (n = 1) => ({ x: `${100 * mod * n}%`, opacity: 0.25 });
|
|
19
|
-
const variants = {
|
|
20
|
-
enter: dir(1),
|
|
21
|
-
exit: dir(-1),
|
|
22
|
-
middle: { x: "0%", opacity: 1 },
|
|
23
|
-
};
|
|
24
|
-
const removeImmediately = { exit: { visibility: "hidden" } };
|
|
25
|
-
const createDays = (month) => {
|
|
26
|
-
const start = startOfWeek(startOfMonth(month));
|
|
27
|
-
return eachDayOfInterval({ start, end: add(start, { days: 41 }) });
|
|
28
|
-
};
|
|
29
|
-
const formatMonth = (d, locale) => d.toLocaleDateString(locale, { month: "long" });
|
|
30
|
-
const getOptionsMonth = (id, date, locale) => Array.from({ length: 12 }).map((_, i) => {
|
|
31
|
-
const month = startOfMonth(new Date(1970, i, 1).setMonth(i));
|
|
32
|
-
const label = formatMonth(month, locale);
|
|
33
|
-
return (<option value={label} key={`${id}-${label}`} data-index={i}>
|
|
34
|
-
{label}
|
|
35
|
-
</option>);
|
|
36
|
-
});
|
|
37
|
-
const onChangeUsingKeyboard = {
|
|
38
|
-
ArrowLeft: (date, duration) => (duration === "days" ? sub(date, { days: 1 }) : sub(date, { months: 1 })),
|
|
39
|
-
ArrowRight: (date, duration) => (duration === "days" ? add(date, { days: 1 }) : add(date, { months: 1 })),
|
|
40
|
-
ArrowUp: (date, duration) => (duration === "days" ? sub(date, { weeks: 1 }) : sub(date, { years: 1 })),
|
|
41
|
-
ArrowDown: (date, duration) => (duration === "days" ? add(date, { weeks: 1 }) : add(date, { years: 1 })),
|
|
42
|
-
};
|
|
43
|
-
const focusDate = (origin, root, next, delay = 0) => {
|
|
44
|
-
const d = next.toISOString();
|
|
45
|
-
const select = () => {
|
|
46
|
-
if (origin?.dataset.focustrap) {
|
|
47
|
-
const el = root.current?.querySelector(`button[data-focustrap="${origin?.dataset.focustrap}"]`);
|
|
48
|
-
return setTimeout(() => el?.focus({ preventScroll: true }), delay);
|
|
49
|
-
}
|
|
50
|
-
if (root.current) {
|
|
51
|
-
const element = root.current.querySelector(`button[data-date="${d}"]`);
|
|
52
|
-
if (element)
|
|
53
|
-
return element.focus({ preventScroll: true });
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
if (delay === 0)
|
|
57
|
-
select();
|
|
58
|
-
setTimeout(select, delay);
|
|
59
|
-
};
|
|
60
|
-
const formatYear = (now) => now.getFullYear().toString().padStart(4, "0");
|
|
61
|
-
const inRange = (start, middle, end) => {
|
|
62
|
-
if (start === undefined || end === undefined)
|
|
63
|
-
return false;
|
|
64
|
-
return isAfter(middle, start) && isBefore(middle, end);
|
|
65
|
-
};
|
|
66
|
-
const CalendarBody = (props) => {
|
|
67
|
-
const translate = useTranslations();
|
|
68
|
-
return (<motion.tbody layout variants={variants} custom={props.direction} onKeyDown={props.onKeyDown} className={css(props.styles?.week)}>
|
|
69
|
-
{props.zip.map((week, index) => {
|
|
70
|
-
const weekClassName = Is.function(props.styles?.week) ? props.styles?.week(week) : props.styles?.week;
|
|
71
|
-
return (<tr key={`week-${week.length}-${index}`} className={weekClassName}>
|
|
72
|
-
{week.map((day) => {
|
|
73
|
-
const key = day.toISOString();
|
|
74
|
-
const isSelected = props.rangeMode
|
|
75
|
-
? key === props.range?.to?.toISOString() || key === props.range?.from?.toISOString()
|
|
76
|
-
: key === (props.date ? startOfDay(props.date).toISOString() : undefined);
|
|
77
|
-
const today = isToday(day) && props.markToday;
|
|
78
|
-
const disabledByFn = props.disabledDate?.(day) || false;
|
|
79
|
-
const sameMonth = isSameMonth(day, props.stateDate);
|
|
80
|
-
const disableDate = !sameMonth || disabledByFn;
|
|
81
|
-
const isInRange = props.rangeMode ? inRange(props.range?.from, day, props.range?.to) : false;
|
|
82
|
-
return (<td key={key} align="center" className={css("relative", Is.function(props.styles?.dayFrame) ? props.styles?.dayFrame(day) : props.styles?.dayFrame)}>
|
|
83
|
-
<button type="button" data-date={key} disabled={disabledByFn} data-samemonth={sameMonth} data-range={props.rangeMode} onClick={props.dispatch.onSelectDate} data-view={props.stateDate.getMonth().toString()} className={css(`flex size-10 items-center justify-center rounded-full proportional-nums disabled:cursor-not-allowed ${today ? "text-emphasis" : ""} ${disableDate ? "text-disabled" : ""} ${isSelected ? "bg-primary text-primary-foreground" : ""}`, isInRange && props.markRange ? "size-10 border border-dashed border-card-border" : "", Is.function(props.styles?.day) ? props.styles?.day(day) : props.styles?.day)}>
|
|
84
|
-
{day.getDate()}
|
|
85
|
-
{isSelected && props.stateRange.from?.toISOString() === key ? (<span className="absolute -top-2 left-0 h-full w-full">
|
|
86
|
-
<span className="text-xs text-foreground">
|
|
87
|
-
{props.labelRange?.from ?? translate.calendarFromDate}
|
|
88
|
-
</span>
|
|
89
|
-
</span>) : null}
|
|
90
|
-
{isSelected && props.stateRange.to?.toISOString() === key ? (<span className="absolute -top-2 left-0 h-full w-full">
|
|
91
|
-
<span className="text-xs text-foreground">{props.labelRange?.to ?? translate.calendarToDate}</span>
|
|
92
|
-
</span>) : null}
|
|
93
|
-
</button>
|
|
94
|
-
{props.RenderOnDay ? <props.RenderOnDay date={day}/> : null}
|
|
95
|
-
</td>);
|
|
96
|
-
})}
|
|
97
|
-
</tr>);
|
|
98
|
-
})}
|
|
99
|
-
</motion.tbody>);
|
|
100
|
-
};
|
|
101
|
-
const getToday = () => startOfDay(new Date());
|
|
102
|
-
export const Calendar = ({ RenderOnDay, changeOnlyOnClick = false, labelRange, disabledDate, locale, markToday = true, onChangeMonth, onChangeYear, rangeMode = false, onChange, styles, markRange = true, type = "date", datetimeTitle, ...props }) => {
|
|
103
|
-
const id = useRef(uuid());
|
|
104
|
-
const translations = useTranslations();
|
|
105
|
-
const currentLocale = useLocale(locale);
|
|
106
|
-
const root = useRef(null);
|
|
107
|
-
const { date, range } = props;
|
|
108
|
-
const providedDate = date || new Date();
|
|
109
|
-
const monthClicked = useRef(null);
|
|
110
|
-
const [state, dispatch] = useReducer({
|
|
111
|
-
date: providedDate,
|
|
112
|
-
isAnimating: false,
|
|
113
|
-
year: formatYear(providedDate),
|
|
114
|
-
direction: undefined,
|
|
115
|
-
range: { from: range?.from, to: range?.to },
|
|
116
|
-
months: getOptionsMonth(id.current, providedDate, currentLocale),
|
|
117
|
-
selectMode: (rangeMode ? "from" : undefined),
|
|
118
|
-
week: eachDayOfInterval({ start: startOfWeek(providedDate), end: endOfWeek(providedDate) }),
|
|
119
|
-
}, (get) => ({
|
|
120
|
-
onChangeYear: (year) => ({ year }),
|
|
121
|
-
onExitComplete: () => {
|
|
122
|
-
focusDate(monthClicked.current || null, root, get.state().date, 200);
|
|
123
|
-
monthClicked.current = null;
|
|
124
|
-
return { isAnimating: false };
|
|
125
|
-
},
|
|
126
|
-
date: (callback) => {
|
|
127
|
-
const newDate = callback(get.state().date);
|
|
128
|
-
return { date: newDate, year: formatYear(newDate) };
|
|
129
|
-
},
|
|
130
|
-
nextMonth: (e) => {
|
|
131
|
-
if (e)
|
|
132
|
-
monthClicked.current = e.currentTarget;
|
|
133
|
-
const state = get.state();
|
|
134
|
-
if (state.isAnimating)
|
|
135
|
-
return state;
|
|
136
|
-
const date = add(state.date, { months: 1 });
|
|
137
|
-
return { date, isAnimating: true, direction: 1, year: formatYear(date) };
|
|
138
|
-
},
|
|
139
|
-
previousMonth: (e) => {
|
|
140
|
-
if (e)
|
|
141
|
-
monthClicked.current = e.currentTarget;
|
|
142
|
-
const state = get.state();
|
|
143
|
-
if (state.isAnimating)
|
|
144
|
-
return state;
|
|
145
|
-
const date = sub(state.date, { months: 1 });
|
|
146
|
-
return { date, isAnimating: true, direction: -1, year: formatYear(date) };
|
|
147
|
-
},
|
|
148
|
-
onSelectDate: (e) => {
|
|
149
|
-
const state = get.state();
|
|
150
|
-
const isRangeMode = e.currentTarget.dataset.range === "true";
|
|
151
|
-
const d = e.currentTarget.dataset.date || "";
|
|
152
|
-
const date = new Date(d);
|
|
153
|
-
return {
|
|
154
|
-
date,
|
|
155
|
-
year: formatYear(date),
|
|
156
|
-
selectMode: state.selectMode === undefined ? undefined : state.selectMode === "from" ? "to" : "from",
|
|
157
|
-
range: !isRangeMode
|
|
158
|
-
? state.range
|
|
159
|
-
: {
|
|
160
|
-
from: state.selectMode === "from" ? date : state.range.from,
|
|
161
|
-
to: state.selectMode === "to" ? date : state.range.to,
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
},
|
|
165
|
-
onChangeMonth: (e) => {
|
|
166
|
-
const value = e.target.value;
|
|
167
|
-
const array = Array.from(e.target.options);
|
|
168
|
-
const month = array.find((x) => x.value === value);
|
|
169
|
-
const state = get.state();
|
|
170
|
-
if (month) {
|
|
171
|
-
const i = month.dataset.index || "";
|
|
172
|
-
const d = new Date(get.state().date);
|
|
173
|
-
d.setMonth(+i);
|
|
174
|
-
return { ...state, date: d, year: formatYear(d) };
|
|
175
|
-
}
|
|
176
|
-
return state;
|
|
177
|
-
},
|
|
178
|
-
onKeyDown: (e) => {
|
|
179
|
-
const key = e.key;
|
|
180
|
-
const state = get.state();
|
|
181
|
-
if (key in onChangeUsingKeyboard) {
|
|
182
|
-
if (key === "ArrowUp" || key === "ArrowDown")
|
|
183
|
-
e.preventDefault();
|
|
184
|
-
const prev = get.state().date;
|
|
185
|
-
const date = Is.keyof(onChangeUsingKeyboard, key) ? onChangeUsingKeyboard[key](prev, e.shiftKey ? "month" : "days") : null;
|
|
186
|
-
if (date !== null) {
|
|
187
|
-
focusDate(e.target, root, date);
|
|
188
|
-
return { ...state, date, year: formatYear(date) };
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return get.state();
|
|
192
|
-
},
|
|
193
|
-
}), {
|
|
194
|
-
props: { onChangeMonth, onChangeYear },
|
|
195
|
-
postMiddleware: [
|
|
196
|
-
(state, _, args) => {
|
|
197
|
-
const isValidMethod = args.method === "onChangeMonth" || args.method === "previousMonth" || args.method === "nextMonth";
|
|
198
|
-
if (isValidMethod)
|
|
199
|
-
args.props.onChangeMonth?.(state.date);
|
|
200
|
-
return state;
|
|
201
|
-
},
|
|
202
|
-
(state, _, args) => {
|
|
203
|
-
const isValidMethod = args.method === "onChangeYear";
|
|
204
|
-
if (isValidMethod)
|
|
205
|
-
args.props.onChangeYear?.(state.date);
|
|
206
|
-
return state;
|
|
207
|
-
},
|
|
208
|
-
(state, _, args) => {
|
|
209
|
-
const isValidMethod = args.method === "onSelectDate" || args.method === "setToday" || args.method === "onKeyDown";
|
|
210
|
-
if (rangeMode && isValidMethod && changeOnlyOnClick) {
|
|
211
|
-
onChange?.(state.range);
|
|
212
|
-
return state;
|
|
213
|
-
}
|
|
214
|
-
if (isValidMethod && changeOnlyOnClick)
|
|
215
|
-
onChange?.(state.date);
|
|
216
|
-
return state;
|
|
217
|
-
},
|
|
218
|
-
],
|
|
219
|
-
});
|
|
220
|
-
const allDaysOfMonth = createDays(state.date);
|
|
221
|
-
const zip = splitInto(allDaysOfMonth, 7);
|
|
222
|
-
const currentAsString = state.date.toISOString();
|
|
223
|
-
const monthString = formatMonth(state.date, currentLocale);
|
|
224
|
-
useEffect(() => {
|
|
225
|
-
if (!changeOnlyOnClick)
|
|
226
|
-
onChange?.(state.date);
|
|
227
|
-
}, [currentAsString, changeOnlyOnClick]);
|
|
228
|
-
const defer = useDebounce((y) => dispatch.date((prev) => setYear(new Date(prev), +y)), 1200);
|
|
229
|
-
const internalOnChangeYear = (e) => {
|
|
230
|
-
const value = e.currentTarget.value;
|
|
231
|
-
dispatch.onChangeYear(value);
|
|
232
|
-
onChangeYear?.(new Date(value));
|
|
233
|
-
defer(value);
|
|
234
|
-
};
|
|
235
|
-
const swipe = useSwipe((event, direction) => {
|
|
236
|
-
event.preventDefault();
|
|
237
|
-
return direction === "right" ? dispatch.previousMonth() : dispatch.nextMonth();
|
|
238
|
-
}, 10);
|
|
239
|
-
const onSetToday = () => {
|
|
240
|
-
const d = getToday();
|
|
241
|
-
dispatch.date(() => d);
|
|
242
|
-
onChange?.(d);
|
|
243
|
-
};
|
|
244
|
-
return (<MotionConfig transition={transition}>
|
|
245
|
-
<div ref={root} data-component="calendar" onTouchEnd={swipe.onTouchEnd} onTouchStart={swipe.onTouchStart} className={css("relative overflow-hidden", Is.function(styles?.calendar) ? styles?.calendar(allDaysOfMonth) : styles?.calendar)}>
|
|
246
|
-
<div className="flex flex-col justify-center rounded-sm text-center">
|
|
247
|
-
<AnimatePresence initial={false} mode="popLayout" custom={state.direction} onExitComplete={dispatch.onExitComplete}>
|
|
248
|
-
<motion.div key={monthString} initial="enter" animate="middle" exit="exit">
|
|
249
|
-
<header className="relative flex justify-between">
|
|
250
|
-
<motion.button layout type="button" data-focustrap="prev" variants={removeImmediately} onClick={dispatch.previousMonth} title={translations.calendarBackMonth} className="z-calendar rounded-full p-1.5 hover:bg-primary hover:text-primary-foreground">
|
|
251
|
-
<ChevronLeftIcon className="h-4 w-4"/>
|
|
252
|
-
</motion.button>
|
|
253
|
-
<motion.span layout variants={variants} custom={state.direction} className="absolute inset-0 isolate z-normal flex items-center justify-center font-semibold">
|
|
254
|
-
<span className="flex w-fit items-center justify-center gap-0.5 py-1">
|
|
255
|
-
<select value={monthString} onChange={dispatch.onChangeMonth} aria-label={translations.calendarMonthLabel} style={{ width: `${monthString.length + 1}ch` }} className="cursor-pointer appearance-none bg-transparent capitalize proportional-nums hover:text-primary">
|
|
256
|
-
{state.months}
|
|
257
|
-
</select>
|
|
258
|
-
<TheMaskInput mask="int" maxLength={4} placeholder="YYYY" value={state.year} onChange={internalOnChangeYear} style={{ width: `${state.year.length}ch` }} className="w-16 cursor-pointer appearance-none bg-transparent hover:text-primary"/>
|
|
259
|
-
</span>
|
|
260
|
-
</motion.span>
|
|
261
|
-
<motion.button layout type="button" data-focustrap="next" variants={removeImmediately} onClick={dispatch.nextMonth} title={translations.calendarNextMonth} className="z-calendar rounded-full p-1.5 hover:bg-primary hover:text-primary-foreground">
|
|
262
|
-
<ChevronRightIcon className="h-4 w-4"/>
|
|
263
|
-
</motion.button>
|
|
264
|
-
<div className="absolute inset-0" style={{
|
|
265
|
-
backgroundImage: "linear-gradient(to right, hsla(var(--card-background)) 15%, transparent 30%, transparent 70%, hsla(var(--card-background)) 85%)",
|
|
266
|
-
}}/>
|
|
267
|
-
</header>
|
|
268
|
-
<motion.table className="mt-2 table min-w-full table-auto border-0">
|
|
269
|
-
<thead>
|
|
270
|
-
<tr>
|
|
271
|
-
{state.week.map((dayOfWeek) => (<th role="columnheader" key={dayOfWeek.toString()} className={css("py-2 text-sm font-medium capitalize", Is.function(styles?.weekDay) ? styles.weekDay(dayOfWeek) : styles?.weekDay)}>
|
|
272
|
-
{dayOfWeek.toLocaleDateString(currentLocale, { weekday: "short" })}
|
|
273
|
-
</th>))}
|
|
274
|
-
</tr>
|
|
275
|
-
</thead>
|
|
276
|
-
<CalendarBody zip={zip} range={range} styles={styles} date={date || null} dispatch={dispatch} markRange={markRange} markToday={markToday} rangeMode={rangeMode} stateDate={state.date} labelRange={labelRange} stateRange={state.range} RenderOnDay={RenderOnDay} direction={state.direction} disabledDate={disabledDate} onKeyDown={dispatch.onKeyDown}/>
|
|
277
|
-
</motion.table>
|
|
278
|
-
</motion.div>
|
|
279
|
-
</AnimatePresence>
|
|
280
|
-
</div>
|
|
281
|
-
{type === "datetime" ? (<section className="grid items-center my-4">
|
|
282
|
-
<Input info={null} mask="time" optionalText=" " container="w-full" reportStatus={false} defaultValue={date ? format(date, "HH:mm") : undefined} title={datetimeTitle || translations.calendarDatetimeTitle} onChange={e => {
|
|
283
|
-
const value = e.target.value;
|
|
284
|
-
const match = timeRegex.exec(value);
|
|
285
|
-
if (!match)
|
|
286
|
-
return;
|
|
287
|
-
const hour = match.groups.hour;
|
|
288
|
-
const min = match.groups.min;
|
|
289
|
-
const d = set(state.date, { hours: Number(hour), minutes: Number(min), seconds: 0 });
|
|
290
|
-
dispatch.date(() => d);
|
|
291
|
-
onChange?.(d);
|
|
292
|
-
}}/>
|
|
293
|
-
</section>) : null}
|
|
294
|
-
<footer className="mt-2 text-center text-primary">
|
|
295
|
-
<button type="button" onClick={onSetToday} className="transition-transform duration-300 hover:scale-105">
|
|
296
|
-
{translations.calendarToday}
|
|
297
|
-
</button>
|
|
298
|
-
</footer>
|
|
299
|
-
</div>
|
|
300
|
-
</MotionConfig>);
|
|
301
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { InfoIcon } from "lucide-react";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { Is } from "sidekicker";
|
|
4
|
-
import { css } from "../../lib/dom";
|
|
5
|
-
import { Polymorph } from "../core/polymorph";
|
|
6
|
-
import { Skeleton } from "./skeleton";
|
|
7
|
-
export const Card = ({ title, loading, children, as, header = null, container = "", titleClassName = "", ...props }) => (<Polymorph {...props} as={as || "div"} data-component="card" className={css("flex shadow-shadow-card flex-col gap-4 rounded-card border border-card-border bg-card-background w-full py-4", container)}>
|
|
8
|
-
{title ? (<header data-component="card-title" className={css("mb-2 w-full border-b border-card-border px-6 pb-4 text-xl font-medium", titleClassName)}>
|
|
9
|
-
{title}
|
|
10
|
-
</header>) : (header)}
|
|
11
|
-
<div data-component="card-body" className={css("min-w-full px-6", props.className)}>
|
|
12
|
-
{loading ? (<div className="flex flex-col gap-4">
|
|
13
|
-
<Skeleton className="w-full"/>
|
|
14
|
-
<Skeleton className="w-8/12"/>
|
|
15
|
-
<Skeleton className="w-10/12"/>
|
|
16
|
-
<Skeleton className="w-1/2"/>
|
|
17
|
-
</div>) : children}
|
|
18
|
-
</div>
|
|
19
|
-
</Polymorph>);
|
|
20
|
-
Card.Title = ({ as, titleTag, navTag, children, ...props }) => {
|
|
21
|
-
const Component = (as || "div");
|
|
22
|
-
const Title = (titleTag || "h2");
|
|
23
|
-
const Nav = (navTag || "nav");
|
|
24
|
-
return (<Component {...props} title={Is.string(props.title) ? props.title : undefined} className={css("flex w-full flex-col flex-wrap items-start justify-between gap-base sm:flex-row sm:items-center", props.className)}>
|
|
25
|
-
<Title className="font-semibold">{props.title}</Title>
|
|
26
|
-
{children ? (<Nav className="flex flex-col justify-start items-start sm:flex-row sm:justify-end sm:items-center gap-kilo">{children}</Nav>) : null}
|
|
27
|
-
</Component>);
|
|
28
|
-
};
|
|
29
|
-
export const StatsCard = (props) => {
|
|
30
|
-
const interactive = props.interactive ?? true;
|
|
31
|
-
const Icon = props.Icon ?? InfoIcon;
|
|
32
|
-
return (<Card {...props} title={null} loading={undefined} container="px-0 py-0" className="flex gap-4 items-center px-0">
|
|
33
|
-
<div className={`flex w-full items-center gap-4 rounded-card px-0 lg:px-0 ${interactive ? "transition-colors duration-300 ease-linear hover:bg-primary-hover/10" : ""}`}>
|
|
34
|
-
<div className={css("flex aspect-square h-[stretch] w-20 items-center justify-center rounded-l-card bg-primary p-4 text-primary-foreground", props.mark)}>
|
|
35
|
-
{<Icon size={48}/>}
|
|
36
|
-
</div>
|
|
37
|
-
<div className="flex flex-col gap-2 justify-center py-2">
|
|
38
|
-
<p className="text-lg">{props.title}</p>
|
|
39
|
-
{props.loading ? <Skeleton className="h-10"/> : <p className="text-4xl font-bold tracking-wide">{props.value}</p>}
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
</Card>);
|
|
43
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { FileIcon } from "lucide-react";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { useTranslations } from "../../hooks/use-translations";
|
|
4
|
-
export const Empty = (props) => {
|
|
5
|
-
const Icon = props.Icon ?? FileIcon;
|
|
6
|
-
const translate = useTranslations();
|
|
7
|
-
return (<div className="flex flex-col gap-4 justify-center items-center py-12 px-8 w-full">
|
|
8
|
-
<Icon size={64} className="text-disabled"/>
|
|
9
|
-
<p className="text-disabled">{props.message ?? translate.emptyDataMessage}</p>
|
|
10
|
-
</div>);
|
|
11
|
-
};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { FloatingFocusManager, FloatingOverlay, FloatingPortal, useClick, useDismiss, useFloating, useInteractions, useRole, } from "@floating-ui/react";
|
|
3
|
-
import { AnimatePresence, motion, MotionConfig } from "motion/react";
|
|
4
|
-
import { XIcon } from "lucide-react";
|
|
5
|
-
import React, { Fragment, useCallback, useId, useState } from "react";
|
|
6
|
-
const FloatItem = ({ item, context, setter, get, refs }) => (<FloatingPortal>
|
|
7
|
-
<MotionConfig reducedMotion="user" transition={{ type: "tween", stiffness: 25, duration: 0.3 }}>
|
|
8
|
-
<AnimatePresence presenceAffectsLayout>
|
|
9
|
-
{item ? (<motion.div exit={{ opacity: 0 }} animate={{ opacity: 1 }} initial={{ opacity: 0 }} className="pointer-events-none fixed inset-0 top-0 z-overlay h-screen w-screen bg-floating-overlay/70"/>) : null}
|
|
10
|
-
{item ? (<FloatingOverlay lockScroll className="absolute inset-0 z-floating flex items-center justify-center">
|
|
11
|
-
<FloatingFocusManager visuallyHiddenDismiss modal closeOnFocusOut context={context}>
|
|
12
|
-
<motion.div layout layoutId={`item-${item.id}`} className="relative flex h-min w-min min-w-xs flex-col gap-4 rounded-card border border-card-border bg-card-background p-6 py-4 pb-8 shadow-shadow-card" ref={refs.setFloating} {...get()}>
|
|
13
|
-
<nav className="absolute right-4 top-1 lg:right-2">
|
|
14
|
-
<button type="button" onClick={setter} className="p-1 opacity-70 transition-colors hover:text-danger hover:opacity-100 focus:text-danger">
|
|
15
|
-
<XIcon />
|
|
16
|
-
</button>
|
|
17
|
-
</nav>
|
|
18
|
-
<header className="flex w-full flex-wrap items-center justify-between gap-2">
|
|
19
|
-
<h3 className="min-w-full text-balance text-2xl font-medium">{item.title}</h3>
|
|
20
|
-
<p className="text-sm leading-snug text-secondary">{item.description}</p>
|
|
21
|
-
</header>
|
|
22
|
-
{item.children}
|
|
23
|
-
</motion.div>
|
|
24
|
-
</FloatingFocusManager>
|
|
25
|
-
</FloatingOverlay>) : null}
|
|
26
|
-
</AnimatePresence>
|
|
27
|
-
</MotionConfig>
|
|
28
|
-
</FloatingPortal>);
|
|
29
|
-
export const AnimatedList = (props) => {
|
|
30
|
-
const [selected, setSelected] = useState(null);
|
|
31
|
-
const id = useId();
|
|
32
|
-
const { context, refs } = useFloating({
|
|
33
|
-
open: selected !== null,
|
|
34
|
-
transform: true,
|
|
35
|
-
onOpenChange: (open) => (open ? undefined : setSelected(null)),
|
|
36
|
-
});
|
|
37
|
-
const click = useClick(context);
|
|
38
|
-
const role = useRole(context, { role: "dialog" });
|
|
39
|
-
const dismiss = useDismiss(context, { escapeKey: true, referencePress: true, outsidePress: true });
|
|
40
|
-
const { getFloatingProps } = useInteractions([click, role, dismiss]);
|
|
41
|
-
const clear = useCallback(() => {
|
|
42
|
-
setSelected(null);
|
|
43
|
-
}, []);
|
|
44
|
-
const items = React.Children.toArray(props.children);
|
|
45
|
-
return (<Fragment>
|
|
46
|
-
<FloatItem refs={refs} context={context} get={getFloatingProps} item={selected} setter={clear}/>
|
|
47
|
-
<ul role="list">
|
|
48
|
-
{items.map((x, index) => {
|
|
49
|
-
const item = x.props;
|
|
50
|
-
const innerId = `${id}-${index}`;
|
|
51
|
-
const setter = () => setSelected({ ...item, id: innerId });
|
|
52
|
-
const Leading = item.leading;
|
|
53
|
-
return (<motion.li layout key={innerId} layoutId={`item-${innerId}`} className={`border-b border-card-border py-2 last:border-transparent`}>
|
|
54
|
-
<motion.div layoutId={`toast-${innerId}`} className="relative">
|
|
55
|
-
<div className="relative flex items-start space-x-3">
|
|
56
|
-
<Fragment>
|
|
57
|
-
{item.avatar ? (<div>
|
|
58
|
-
<div className="relative px-1">
|
|
59
|
-
<button onClick={setter} className="flex size-10 items-center justify-center ring-primary">
|
|
60
|
-
{item.avatar}
|
|
61
|
-
</button>
|
|
62
|
-
</div>
|
|
63
|
-
</div>) : null}
|
|
64
|
-
<div className="min-w-0 flex-1 py-1 text-foreground">
|
|
65
|
-
<div className="flex flex-row flex-nowrap justify-between gap-4">
|
|
66
|
-
<button onClick={setter} className="cursor-pointer text-left transition-all ease-out hover:text-primary">
|
|
67
|
-
<h3>{item.title}</h3>
|
|
68
|
-
<p className="text-sm leading-snug text-secondary">{item.description}</p>
|
|
69
|
-
</button>
|
|
70
|
-
{Leading ? <Leading open={setter}/> : null}
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
</Fragment>
|
|
74
|
-
</div>
|
|
75
|
-
</motion.div>
|
|
76
|
-
</motion.li>);
|
|
77
|
-
})}
|
|
78
|
-
</ul>
|
|
79
|
-
</Fragment>);
|
|
80
|
-
};
|
|
81
|
-
export const AnimatedListItem = (props) => <Fragment>{props.children}</Fragment>;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { cva } from "class-variance-authority";
|
|
3
|
-
import { XIcon } from "lucide-react";
|
|
4
|
-
import { AnimatePresence, motion } from "motion/react";
|
|
5
|
-
import { Toast as Base } from "@base-ui/react/toast";
|
|
6
|
-
import { createContext, useCallback, useContext, useRef } from "react";
|
|
7
|
-
import { useHover } from "../../hooks/use-hover";
|
|
8
|
-
const variants = cva("relative isolate z-tooltip flex justify-between overflow-hidden whitespace-wrap rounded-lg border text-sm shadow-shadow-notification", {
|
|
9
|
-
variants: {
|
|
10
|
-
theme: {
|
|
11
|
-
default: "border-card-border bg-card-background text-foreground",
|
|
12
|
-
info: "bg-alert-info-bg text-alert-info-text border-alert-info-border",
|
|
13
|
-
warn: "bg-alert-warn-bg text-alert-warn-text border-alert-warn-border",
|
|
14
|
-
muted: "bg-alert-muted-bg text-alert-muted-text border-alert-muted-border",
|
|
15
|
-
danger: "bg-alert-danger-bg text-alert-danger-text border-alert-danger-border",
|
|
16
|
-
success: "bg-alert-success-bg text-alert-success-text border-alert-success-border",
|
|
17
|
-
secondary: "bg-alert-secondary-bg text-alert-secondary-text border-alert-secondary-border",
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
defaultVariants: { theme: "default" },
|
|
21
|
-
});
|
|
22
|
-
const NotificationContext = createContext(() => {
|
|
23
|
-
throw new Error("Not implemented");
|
|
24
|
-
});
|
|
25
|
-
export const useNotification = () => useContext(NotificationContext);
|
|
26
|
-
const animatedIndex = {
|
|
27
|
-
0: { opacity: 1, y: [10, 15], scale: [1, 0.98] },
|
|
28
|
-
1: { opacity: 1, y: [15, 20], scale: [1, 0.97] },
|
|
29
|
-
2: { opacity: 1, y: [20, 25], scale: [1, 0.96] },
|
|
30
|
-
default: { opacity: 1, y: [25, 30], scale: [1, 0.95] },
|
|
31
|
-
};
|
|
32
|
-
function Notification(props) {
|
|
33
|
-
const closable = props.toast.data?.closable ?? true;
|
|
34
|
-
const variant = props.hover ? "hover" : props.isLast ? "isLast" : "other";
|
|
35
|
-
const className = variants({ theme: props.toast.data?.theme || "default" });
|
|
36
|
-
return (<Base.Root toast={props.toast} swipeDirection={["down", "right"]}>
|
|
37
|
-
<motion.li layout layoutScroll animate={variant} data-index={props.index} initial={{ y: -100, zIndex: -1 }} className="absolute top-0 right-0 w-80 pointer-events-auto text-select" transition={{ type: "spring", mass: 1.2, damping: 30, stiffness: 200 }} exit={{ opacity: [0.9, 0], transition: { opacity: { bounce: 0.25, duration: 0.3 } } }} variants={{
|
|
38
|
-
isLast: { y: 10, scale: 1, animationDuration: "300ms", opacity: 1 },
|
|
39
|
-
hover: { y: 0, position: "static", scale: 1, opacity: 1 },
|
|
40
|
-
other: animatedIndex[props.reversedIndex] || animatedIndex.default,
|
|
41
|
-
}}>
|
|
42
|
-
<Base.Content className={className}>
|
|
43
|
-
<div className="flex flex-col p-4">
|
|
44
|
-
{props.toast.title ? (<Base.Title className="text-lg font-medium leading-relaxed select-text"/>) : null}
|
|
45
|
-
<Base.Description className="select-text"/>
|
|
46
|
-
</div>
|
|
47
|
-
{closable ? (<Base.Close className="absolute top-2 right-2 p-1 rounded-full transition text-foreground hover:bg-danger/10 hover:text-danger-hover">
|
|
48
|
-
<XIcon className="size-5"/>
|
|
49
|
-
</Base.Close>) : null}
|
|
50
|
-
</Base.Content>
|
|
51
|
-
</motion.li>
|
|
52
|
-
</Base.Root>);
|
|
53
|
-
}
|
|
54
|
-
function NotificationsViewport({ max = 5 }) {
|
|
55
|
-
const ref = useRef(null);
|
|
56
|
-
const hover = useHover(ref);
|
|
57
|
-
const toastManager = Base.useToastManager();
|
|
58
|
-
const toasts = toastManager.toasts.slice(-max);
|
|
59
|
-
return (<Base.Viewport ref={ref} data-items={toasts.length} style={{
|
|
60
|
-
justifyContent: "start",
|
|
61
|
-
height: `${(hover ? toasts.length : Math.min(1, toasts.length)) * 7}rem`,
|
|
62
|
-
}} className="fixed right-4 top-10 flex w-80 list-none flex-col-reverse items-end gap-4 overflow-y-clip overflow-x-visible data-[items=true]:pb-8 max-sm:top-20">
|
|
63
|
-
<motion.ol className="flex flex-col gap-4">
|
|
64
|
-
<AnimatePresence presenceAffectsLayout mode="popLayout">
|
|
65
|
-
{toasts.reverse().map((toast, index, list) => (<Notification toast={toast} hover={hover} index={index} key={toast.id} isLast={list.length - 1 === index} reversedIndex={list.length - (index + 1)}/>))}
|
|
66
|
-
</AnimatePresence>
|
|
67
|
-
</motion.ol>
|
|
68
|
-
</Base.Viewport>);
|
|
69
|
-
}
|
|
70
|
-
function NotificationsInner({ children, max = 5 }) {
|
|
71
|
-
const toastManager = Base.useToastManager();
|
|
72
|
-
const clear = useCallback(() => {
|
|
73
|
-
toastManager.toasts.forEach((t) => toastManager.close(t.id));
|
|
74
|
-
}, [toastManager]);
|
|
75
|
-
const notify = useCallback((description, args) => {
|
|
76
|
-
const id = toastManager.add({
|
|
77
|
-
description,
|
|
78
|
-
title: args?.title,
|
|
79
|
-
timeout: args?.timeout,
|
|
80
|
-
data: { theme: args?.theme, closable: args?.closable },
|
|
81
|
-
});
|
|
82
|
-
return {
|
|
83
|
-
close: () => toastManager.close(id),
|
|
84
|
-
clear,
|
|
85
|
-
};
|
|
86
|
-
}, [toastManager, clear]);
|
|
87
|
-
return (<NotificationContext.Provider value={notify}>
|
|
88
|
-
{children}
|
|
89
|
-
<Base.Portal>
|
|
90
|
-
<NotificationsViewport max={max}/>
|
|
91
|
-
</Base.Portal>
|
|
92
|
-
</NotificationContext.Provider>);
|
|
93
|
-
}
|
|
94
|
-
export function Notifications({ children, max = 5, timeout = 5000 }) {
|
|
95
|
-
return (<Base.Provider limit={max} timeout={timeout}>
|
|
96
|
-
<NotificationsInner max={max}>{children}</NotificationsInner>
|
|
97
|
-
</Base.Provider>);
|
|
98
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Is } from "sidekicker";
|
|
2
|
-
import { Progress as ProgressBar } from "@base-ui/react/progress";
|
|
3
|
-
import { css } from "../../lib/dom";
|
|
4
|
-
export const Progress = (props) => {
|
|
5
|
-
return (<ProgressBar.Root max={props.max} value={props.percent ?? null} style={{ transform: "translateZ(0)", }} className={css("overflow-hidden relative w-full rounded-full h-6 bg-background", props.container)}>
|
|
6
|
-
<ProgressBar.Indicator style={{ transform: Is.number(props.percent) ? `translateX(-${100 - props.percent}%)` : undefined }} className={css("bg-primary transition-transform ease-in-out size-full duration-500", props.className)}/>
|
|
7
|
-
{Is.number(props.percent)
|
|
8
|
-
? <p className={css("flex absolute inset-0 justify-center items-center w-full font-semibold tabular-nums text-primary-foreground", props.textClassName)}>
|
|
9
|
-
{props.label ? props.label : `${props.percent} %`}
|
|
10
|
-
</p>
|
|
11
|
-
: null}
|
|
12
|
-
</ProgressBar.Root>);
|
|
13
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { CommandIcon, OptionIcon } from "lucide-react";
|
|
2
|
-
import { Fragment } from "react";
|
|
3
|
-
import { isMac } from "../../lib/combi-keys";
|
|
4
|
-
const remap = (x) => {
|
|
5
|
-
x = x.trim();
|
|
6
|
-
if (x === "Alt")
|
|
7
|
-
return isMac() ? <OptionIcon aria-label="Option" size={12}/> : "Alt";
|
|
8
|
-
if (x === "Mod")
|
|
9
|
-
return isMac() ? <CommandIcon aria-label="Command" size={12}/> : "Ctrl";
|
|
10
|
-
return x;
|
|
11
|
-
};
|
|
12
|
-
export const Shortcut = (props) => {
|
|
13
|
-
const p = props.value.trim().split("+");
|
|
14
|
-
return (<span className="flex text-sm items-center gap-1">
|
|
15
|
-
{p.map((x, i) => {
|
|
16
|
-
const isLast = p.length - 1 === i;
|
|
17
|
-
return (<Fragment key={`${props.value}-${x}-key-${i}`}>
|
|
18
|
-
<kbd aria-label={x}>{remap(x)}</kbd>
|
|
19
|
-
{isLast ? null : <span>+</span>}
|
|
20
|
-
</Fragment>);
|
|
21
|
-
})}
|
|
22
|
-
</span>);
|
|
23
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React, { useRef } from "react";
|
|
2
|
-
import { css } from "../../lib/dom";
|
|
3
|
-
import { Polymorph } from "../core/polymorph";
|
|
4
|
-
export const SkeletonCell = <div className="w-10/12 h-6 rounded-sm animate-pulse bg-muted"/>;
|
|
5
|
-
export const Skeleton = (props) => (<Polymorph {...props} as={props.as || "span"} className={css("block rounded-sm h-8 w-32 animate-pulse bg-muted", props.className)}/>);
|
|
6
|
-
export const SkeletonList = (props) => {
|
|
7
|
-
const items = useRef(Array.from({ length: props.rows }).map((_, i) => {
|
|
8
|
-
const rand = Math.max(100, Math.random() * 99);
|
|
9
|
-
return <Skeleton key={`skeleton-${rand}-${i}`} style={{ width: `${rand}%` }} as="li"/>;
|
|
10
|
-
}));
|
|
11
|
-
return (<ul className={css("flex flex-col gap-6", props.className)}>
|
|
12
|
-
{items.current}
|
|
13
|
-
</ul>);
|
|
14
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { css } from "../../lib/dom";
|
|
2
|
-
export const Spinner = (props) => (<span aria-busy="true" aria-description="Carregando..." className={css("box-border inline-block aspect-square size-12 animate-spin rounded-full border-4 border-background border-b-primary", props.className)}/>);
|
|
3
|
-
export const Loading = () => {
|
|
4
|
-
return (<div className="flex h-full w-full items-center justify-center p-12">
|
|
5
|
-
<Spinner />
|
|
6
|
-
</div>);
|
|
7
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { css } from "../../lib/dom";
|
|
3
|
-
export const Stats = (props) => {
|
|
4
|
-
return (<div className="divide-y divide-card-border rounded-card border border-card-border bg-card-background shadow-shadow-card">
|
|
5
|
-
<header className="flex items-start gap-4 p-6">
|
|
6
|
-
<div className={css("flex aspect-square size-10 items-center justify-center rounded-card bg-primary p-8", props.iconContainer)}>
|
|
7
|
-
<div>
|
|
8
|
-
<props.Icon className="aspect-square size-10 text-primary-foreground"/>
|
|
9
|
-
</div>
|
|
10
|
-
</div>
|
|
11
|
-
<div className="flex flex-col gap-1">
|
|
12
|
-
<header>
|
|
13
|
-
<h3 className="text-base leading-none">{props.title}</h3>
|
|
14
|
-
</header>
|
|
15
|
-
<p className="text-4xl font-semibold">{props.children}</p>
|
|
16
|
-
</div>
|
|
17
|
-
</header>
|
|
18
|
-
{props.footer ? <footer className="px-6 py-2">{props.footer}</footer> : null}
|
|
19
|
-
</div>);
|
|
20
|
-
};
|