@g4rcez/components 3.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/tag.d.ts +1 -1
- package/dist/components/core/tag.d.ts.map +1 -1
- package/dist/components/display/list.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.map +1 -1
- package/dist/config/default-translations.d.ts +4 -4
- package/dist/hooks/use-translations.d.ts +4 -4
- package/dist/hooks/use-translations.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +28 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2463 -2458
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +12 -12
- package/dist/index.umd.js.map +1 -1
- package/package.json +4 -4
- package/dist/components/core/button.jsx +0 -79
- 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 -156
- package/dist/components/core/tag.jsx +0 -51
- package/dist/components/core/typography.jsx +0 -22
- package/dist/components/display/alert.jsx +0 -58
- package/dist/components/display/calendar.jsx +0 -299
- 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 -126
- package/dist/components/display/progress.jsx +0 -11
- package/dist/components/display/shortcut.jsx +0 -23
- package/dist/components/display/skeleton.jsx +0 -12
- 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 -98
- package/dist/components/display/timeline.jsx +0 -25
- package/dist/components/floating/command-palette.jsx +0 -194
- 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 -299
- package/dist/components/floating/toolbar.jsx +0 -5
- package/dist/components/floating/tooltip.jsx +0 -58
- package/dist/components/floating/wizard.jsx +0 -161
- package/dist/components/form/autocomplete.jsx +0 -279
- 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 -56
- 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 -45
- package/dist/components/page-calendar/calendar-header.jsx +0 -81
- package/dist/components/page-calendar/day-view.jsx +0 -87
- package/dist/components/page-calendar/event-pill.jsx +0 -25
- package/dist/components/page-calendar/index.js +0 -2
- package/dist/components/page-calendar/month-view.jsx +0 -47
- package/dist/components/page-calendar/page-calendar.jsx +0 -41
- package/dist/components/page-calendar/page-calendar.types.js +0 -1
- package/dist/components/page-calendar/page-calendar.utils.js +0 -71
- package/dist/components/page-calendar/week-view.jsx +0 -64
- 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 -36
- 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 -83
- 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 -83
- 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 -19
- package/dist/hooks/use-debounce.js +0 -12
- package/dist/hooks/use-floating-ref.js +0 -6
- package/dist/hooks/use-form.js +0 -550
- 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 -9
- package/dist/hooks/use-reactive.js +0 -9
- 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 -9
- package/dist/hooks/use-swipe.js +0 -17
- 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 -62
- package/dist/lib/fns.js +0 -46
- package/dist/lib/fzf.js +0 -117
- package/dist/lib/keyboard-area.js +0 -14
- package/dist/styles/common.js +0 -29
- package/dist/styles/dark.js +0 -214
- package/dist/styles/design-tokens.js +0 -69
- package/dist/styles/light.js +0 -214
- package/dist/styles/theme.js +0 -4
- package/dist/styles/theme.types.js +0 -1
- package/dist/types.js +0 -1
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { autoUpdate, flip, FloatingFocusManager, FloatingList, FloatingNode, FloatingPortal, FloatingTree, offset, safePolygon, shift, useClick, useDismiss, useFloating, useFloatingNodeId, useFloatingParentNodeId, useFloatingTree, useHover, useInteractions, useListItem, useListNavigation, useRole, useTypeahead, } from "@floating-ui/react";
|
|
3
|
-
import { Slot } from "../core/slot";
|
|
4
|
-
import { ChevronRightIcon } from "lucide-react";
|
|
5
|
-
import React, { createContext, Fragment, useContext, useEffect, useRef, useState } from "react";
|
|
6
|
-
import { FLOATING_DELAY, TYPEAHEAD_RESET_DELAY } from "../../constants";
|
|
7
|
-
import { css, mergeRefs } from "../../lib/dom";
|
|
8
|
-
const menuItemClassName = (highlight = "") => css("w-full min-w-36 outline-none p-2.5 items-center flex justify-between text-left", "hover:bg-primary focus:bg-primary aria-expanded:opacity-80", "focus:text-primary-foreground hover:text-primary-foreground", "first-of-type:rounded-t-lg last-of-type:rounded-b-lg", "disabled:opacity-40 disabled:cursor-not-allowed", highlight);
|
|
9
|
-
const MenuContext = createContext({
|
|
10
|
-
isOpen: false,
|
|
11
|
-
activeIndex: null,
|
|
12
|
-
getItemProps: () => ({}),
|
|
13
|
-
setActiveIndex: () => { },
|
|
14
|
-
setHasFocusInside: () => { },
|
|
15
|
-
});
|
|
16
|
-
const MenuComponent = React.forwardRef(({ children, FloatingComponent = "div", hover = true, open, isParent = false, restoreFocus = false, floatingClassName = "", label, ...props }, forwardedRef) => {
|
|
17
|
-
const [isOpen, setIsOpen] = useState(open ?? false);
|
|
18
|
-
const [hasFocusInside, setHasFocusInside] = useState(false);
|
|
19
|
-
const [activeIndex, setActiveIndex] = useState(null);
|
|
20
|
-
const elementsRef = useRef([]);
|
|
21
|
-
const labelsRef = useRef([]);
|
|
22
|
-
const parent = useContext(MenuContext);
|
|
23
|
-
const parentId = useFloatingParentNodeId();
|
|
24
|
-
const tree = useFloatingTree();
|
|
25
|
-
const nodeId = useFloatingNodeId();
|
|
26
|
-
const item = useListItem();
|
|
27
|
-
const isNested = parentId !== null;
|
|
28
|
-
const { floatingStyles, refs, context } = useFloating({
|
|
29
|
-
nodeId,
|
|
30
|
-
open: isOpen,
|
|
31
|
-
transform: true,
|
|
32
|
-
strategy: "absolute",
|
|
33
|
-
onOpenChange: setIsOpen,
|
|
34
|
-
whileElementsMounted: autoUpdate,
|
|
35
|
-
placement: isNested ? "right" : "bottom-start",
|
|
36
|
-
middleware: [offset({ mainAxis: isNested ? 0 : 4, alignmentAxis: isNested ? -4 : 0 }), flip(), shift()],
|
|
37
|
-
});
|
|
38
|
-
const role = useRole(context, { role: "menu" });
|
|
39
|
-
const dismiss = useDismiss(context, { bubbles: true });
|
|
40
|
-
const hoverModule = useHover(context, {
|
|
41
|
-
move: false,
|
|
42
|
-
enabled: hover,
|
|
43
|
-
delay: { open: FLOATING_DELAY },
|
|
44
|
-
handleClose: safePolygon({ blockPointerEvents: true, requireIntent: false }),
|
|
45
|
-
});
|
|
46
|
-
const click = useClick(context, {
|
|
47
|
-
toggle: !isNested,
|
|
48
|
-
event: "mousedown",
|
|
49
|
-
ignoreMouse: isNested,
|
|
50
|
-
keyboardHandlers: true,
|
|
51
|
-
});
|
|
52
|
-
const listNavigation = useListNavigation(context, {
|
|
53
|
-
loop: true,
|
|
54
|
-
activeIndex,
|
|
55
|
-
nested: isNested,
|
|
56
|
-
listRef: elementsRef,
|
|
57
|
-
onNavigate: setActiveIndex,
|
|
58
|
-
});
|
|
59
|
-
const typeahead = useTypeahead(context, {
|
|
60
|
-
activeIndex,
|
|
61
|
-
listRef: labelsRef,
|
|
62
|
-
resetMs: TYPEAHEAD_RESET_DELAY,
|
|
63
|
-
onMatch: isOpen ? setActiveIndex : undefined,
|
|
64
|
-
});
|
|
65
|
-
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([hoverModule, click, role, dismiss, listNavigation, typeahead]);
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (!tree)
|
|
68
|
-
return;
|
|
69
|
-
const handleTreeClick = () => setIsOpen(false);
|
|
70
|
-
const onSubMenuOpen = (event) => {
|
|
71
|
-
if (event.nodeId !== nodeId && event.parentId === parentId)
|
|
72
|
-
setIsOpen(false);
|
|
73
|
-
};
|
|
74
|
-
tree.events.on("click", handleTreeClick);
|
|
75
|
-
tree.events.on("menuopen", onSubMenuOpen);
|
|
76
|
-
return () => {
|
|
77
|
-
tree.events.off("click", handleTreeClick);
|
|
78
|
-
tree.events.off("menuopen", onSubMenuOpen);
|
|
79
|
-
};
|
|
80
|
-
}, [tree, nodeId, parentId]);
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
if (isOpen && tree)
|
|
83
|
-
tree.events.emit("menuopen", { parentId, nodeId });
|
|
84
|
-
}, [tree, isOpen, nodeId, parentId]);
|
|
85
|
-
const className = isParent ? props.className : css(menuItemClassName(props.className));
|
|
86
|
-
return (<FloatingNode id={nodeId}>
|
|
87
|
-
<Fragment>
|
|
88
|
-
{props.asChild ? (<Slot {...getReferenceProps(parent.getItemProps({
|
|
89
|
-
...props,
|
|
90
|
-
onFocus(event) {
|
|
91
|
-
props.onFocus?.(event);
|
|
92
|
-
setHasFocusInside(false);
|
|
93
|
-
parent.setHasFocusInside(true);
|
|
94
|
-
},
|
|
95
|
-
}))} children={label} className={className} data-open={isOpen ? "" : undefined} data-nested={isNested ? "" : undefined} role={isNested ? "menuitem" : undefined} data-focus-inside={hasFocusInside ? "" : undefined} ref={mergeRefs(refs.setReference, item.ref, forwardedRef)} tabIndex={!isNested ? undefined : parent.activeIndex === item.index ? 0 : -1}/>) : (<button type="button" className={className} data-open={isOpen ? "" : undefined} data-nested={isNested ? "" : undefined} role={isNested ? "menuitem" : undefined} data-focus-inside={hasFocusInside ? "" : undefined} ref={mergeRefs(refs.setReference, item.ref, forwardedRef)} tabIndex={!isNested ? undefined : parent.activeIndex === item.index ? 0 : -1} {...getReferenceProps(parent.getItemProps({
|
|
96
|
-
...props,
|
|
97
|
-
onFocus(event) {
|
|
98
|
-
props.onFocus?.(event);
|
|
99
|
-
setHasFocusInside(false);
|
|
100
|
-
parent.setHasFocusInside(true);
|
|
101
|
-
},
|
|
102
|
-
}))}>
|
|
103
|
-
{label}
|
|
104
|
-
{isNested && (<span style={{ marginLeft: 10, fontSize: 10 }}>
|
|
105
|
-
<span className="sr-only">Next menu</span>
|
|
106
|
-
<ChevronRightIcon size={14}/>
|
|
107
|
-
</span>)}
|
|
108
|
-
</button>)}
|
|
109
|
-
</Fragment>
|
|
110
|
-
<MenuContext.Provider value={{ activeIndex, setActiveIndex, getItemProps, setHasFocusInside, isOpen }}>
|
|
111
|
-
<FloatingList elementsRef={elementsRef} labelsRef={labelsRef}>
|
|
112
|
-
{isOpen && (<FloatingPortal>
|
|
113
|
-
<FloatingFocusManager context={context} modal={false} initialFocus={isNested ? -1 : 0} returnFocus={isParent ? restoreFocus : !isNested}>
|
|
114
|
-
<FloatingComponent {...getFloatingProps()} ref={refs.setFloating} style={{ ...props.style, ...floatingStyles }} className={css("isolate z-tooltip flex max-h-80 flex-col items-start overflow-y-auto rounded-lg border border-floating-border bg-floating-background text-left shadow-shadow-floating outline-none", floatingClassName)}>
|
|
115
|
-
{children}
|
|
116
|
-
</FloatingComponent>
|
|
117
|
-
</FloatingFocusManager>
|
|
118
|
-
</FloatingPortal>)}
|
|
119
|
-
</FloatingList>
|
|
120
|
-
</MenuContext.Provider>
|
|
121
|
-
</FloatingNode>);
|
|
122
|
-
});
|
|
123
|
-
export const MenuItem = React.forwardRef(({ title, Right, disabled, children, ...props }, forwardedRef) => {
|
|
124
|
-
const menu = useContext(MenuContext);
|
|
125
|
-
const item = useListItem({ label: disabled ? null : title });
|
|
126
|
-
const tree = useFloatingTree();
|
|
127
|
-
const isActive = item.index === menu.activeIndex;
|
|
128
|
-
return (<button {...props} title={title} type="button" role="menuitem" disabled={disabled} data-active={isActive} data-open={menu.isOpen} tabIndex={isActive ? 0 : -1} ref={mergeRefs(item.ref, forwardedRef)} className={menuItemClassName(`${props.className ?? ""} ${isActive ? "bg-primary text-primary-foreground" : ""}`)} {...menu.getItemProps({
|
|
129
|
-
onClick(event) {
|
|
130
|
-
props.onClick?.(event);
|
|
131
|
-
tree?.events.emit("click");
|
|
132
|
-
},
|
|
133
|
-
onFocus(event) {
|
|
134
|
-
props.onFocus?.(event);
|
|
135
|
-
menu.setHasFocusInside(true);
|
|
136
|
-
},
|
|
137
|
-
})}>
|
|
138
|
-
{children}
|
|
139
|
-
{Right ? <Right size={16}/> : null}
|
|
140
|
-
</button>);
|
|
141
|
-
});
|
|
142
|
-
export const Menu = React.forwardRef((props, ref) => {
|
|
143
|
-
const parentId = useFloatingParentNodeId();
|
|
144
|
-
return parentId === null ? (<FloatingTree>
|
|
145
|
-
<MenuComponent {...props} isParent ref={ref}/>
|
|
146
|
-
</FloatingTree>) : (<MenuComponent {...props} isParent={false} ref={ref}/>);
|
|
147
|
-
});
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { FloatingFocusManager, FloatingOverlay, FloatingPortal, useClick, useDismiss, useFloating, useInteractions, useRole, } from "@floating-ui/react";
|
|
3
|
-
import { cva } from "class-variance-authority";
|
|
4
|
-
import { XIcon } from "lucide-react";
|
|
5
|
-
import { AnimatePresence, motion, MotionConfig, useMotionValue, animate, } from "motion/react";
|
|
6
|
-
import { Slot } from "../core/slot";
|
|
7
|
-
import React, { forwardRef, Fragment, useEffect, useId, useImperativeHandle, useRef, useState, useCallback, } from "react";
|
|
8
|
-
import { useMediaQuery } from "../../hooks/use-media-query";
|
|
9
|
-
import { css, mergeRefs } from "../../lib/dom";
|
|
10
|
-
import { useFloatingRef } from "../../hooks/use-floating-ref";
|
|
11
|
-
import { Button } from "../core/button";
|
|
12
|
-
const ConfirmContext = React.createContext(async () => false);
|
|
13
|
-
export const useConfirm = () => React.useContext(ConfirmContext);
|
|
14
|
-
const animationDuration = "500ms";
|
|
15
|
-
const drawerLeft = {
|
|
16
|
-
exit: { x: ["0%", "-30%"], opacity: 0, animationDuration },
|
|
17
|
-
enter: { x: ["-30%", "0%"], opacity: 1, animationDuration },
|
|
18
|
-
initial: { x: ["-30%", "0%"], opacity: 0.8, animationDuration },
|
|
19
|
-
};
|
|
20
|
-
const drawerRight = {
|
|
21
|
-
enter: { x: "0%", opacity: 1, animationDuration },
|
|
22
|
-
exit: { x: ["0%", "30%"], opacity: 0, animationDuration },
|
|
23
|
-
initial: { x: ["30%", "0%"], opacity: 0.8, animationDuration },
|
|
24
|
-
};
|
|
25
|
-
const animations = {
|
|
26
|
-
drawer: (type) => (type === "left" ? drawerLeft : drawerRight),
|
|
27
|
-
sheet: {
|
|
28
|
-
enter: { opacity: 1, y: "0%", animationDuration, transformOrigin: "bottom" },
|
|
29
|
-
exit: { opacity: 0.4, y: "10%", animationDuration, transformOrigin: "bottom" },
|
|
30
|
-
initial: { opacity: 0.7, y: "10%", animationDuration, transformOrigin: "bottom" },
|
|
31
|
-
},
|
|
32
|
-
dialog: {
|
|
33
|
-
exit: { opacity: 0, scale: 0.95, animationDuration },
|
|
34
|
-
enter: { opacity: 1, scale: [1.05, 1], animationDuration },
|
|
35
|
-
initial: { opacity: 0.5, scale: 0.95, animationDuration, transition: { duration: 0.5, ease: "easeInOut" } },
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
const variants = cva("z-floating border border-floating-border ring-0 outline-0 appearance-none flex flex-col gap-4 flex-nowrap min-w-xs bg-floating-background", {
|
|
39
|
-
variants: {
|
|
40
|
-
type: {
|
|
41
|
-
drawer: "max-h-screen max-w-[90%] absolute w-fit h-screen min-h-0",
|
|
42
|
-
dialog: "max-h-[calc(100lvh-10%)] relative container h-min rounded-lg py-4",
|
|
43
|
-
sheet: "w-screen absolute bottom-0 max-h-[calc(100vh-15%)] max-h-[calc(100svh-5%)] h-screen pt-6 pb-4 rounded-t-lg",
|
|
44
|
-
},
|
|
45
|
-
position: {
|
|
46
|
-
none: "",
|
|
47
|
-
right: "py-4 absolute right-0 top-0 rounded-l-lg",
|
|
48
|
-
left: "py-4 absolute left-0 top-0 rounded-r-lg",
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
defaultVariants: { position: "right", type: "dialog" },
|
|
52
|
-
});
|
|
53
|
-
const dragConstraints = { top: 0, left: 0, right: 0, bottom: 0 };
|
|
54
|
-
const calculateClose = (n) => n * 0.6;
|
|
55
|
-
const Draggable = (props) => {
|
|
56
|
-
const onDrag = (e, info) => {
|
|
57
|
-
if (props.parent.current) {
|
|
58
|
-
e.stopPropagation();
|
|
59
|
-
e.stopImmediatePropagation();
|
|
60
|
-
if (props.sheet) {
|
|
61
|
-
const div = props.parent.current;
|
|
62
|
-
const rect = div.getBoundingClientRect();
|
|
63
|
-
const v = props.value.get() || rect.height;
|
|
64
|
-
const result = Math.abs(v - info.delta.y);
|
|
65
|
-
const max = window.outerHeight;
|
|
66
|
-
const screenHeightToClose = calculateClose(max);
|
|
67
|
-
if (result >= screenHeightToClose)
|
|
68
|
-
return props.value.set(result);
|
|
69
|
-
if (document.activeElement instanceof HTMLElement) {
|
|
70
|
-
document.activeElement?.blur();
|
|
71
|
-
}
|
|
72
|
-
props.onChange(false);
|
|
73
|
-
return setTimeout(() => props.value.set(undefined), 350);
|
|
74
|
-
}
|
|
75
|
-
const div = props.parent.current;
|
|
76
|
-
const v = props.value.get() || div.getBoundingClientRect().width;
|
|
77
|
-
const delta = props.position === "right" ? -info.delta.x : info.delta.x;
|
|
78
|
-
const value = Math.abs(v + delta);
|
|
79
|
-
return props.value.set(value);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
return (<motion.button draggable dragListener dragMomentum type="button" animate={false} dragElastic={0} dragPropagation initial={false} onDrag={onDrag} dragSnapToOrigin dragDirectionLock drag={props.sheet ? "y" : "x"} dragConstraints={dragConstraints} whileDrag={{ cursor: "grabbing" }} className={css("absolute isolate z-calendar rounded-lg", props.sheet ? "cursor-row-resize" : "cursor-col-resize bg-floating-border", props.sheet
|
|
83
|
-
? "top-1 flex h-3 w-full justify-center py-2"
|
|
84
|
-
: props.position === "left"
|
|
85
|
-
? "right-5 top-1/2 h-10 w-2"
|
|
86
|
-
: "left-2 top-1/2 h-10 w-2")}>
|
|
87
|
-
{props.sheet ? <div className="h-2 w-1/4 rounded-lg bg-floating-border"/> : null}
|
|
88
|
-
</motion.button>);
|
|
89
|
-
};
|
|
90
|
-
const positions = { drawer: "right", sheet: "none", dialog: "none" };
|
|
91
|
-
const fetchPosition = (isDesktop, forceType, propsType, propsPosition) => {
|
|
92
|
-
const type = propsType || "dialog";
|
|
93
|
-
if (isDesktop)
|
|
94
|
-
return propsType === "drawer" ? (propsPosition ?? positions.drawer) : positions[type];
|
|
95
|
-
return forceType ? positions[type] : positions.sheet;
|
|
96
|
-
};
|
|
97
|
-
const noop = [];
|
|
98
|
-
export const Modal = forwardRef(({ open, title, footer, asChild, trigger, children, onChange, ariaTitle, className, bodyClassName, resizer = true, animated = true, closable = true, forceType = false, layoutId = undefined, overlayClassName = "", type: _type = "dialog", position: propsPosition, overlayClickClose = false, closeOnFocusOut = false, interactions: outInteractions = noop, ...props }, externalRef) => {
|
|
99
|
-
const root = useFloatingRef();
|
|
100
|
-
const innerContent = useRef(null);
|
|
101
|
-
const removeScrollRef = useRef(null);
|
|
102
|
-
const headingId = useId();
|
|
103
|
-
const descriptionId = useId();
|
|
104
|
-
const isDesktop = useMediaQuery("(min-width: 64rem)");
|
|
105
|
-
const position = fetchPosition(isDesktop, forceType, _type, propsPosition);
|
|
106
|
-
const func = isDesktop ? animations[_type] : forceType ? animations[_type] : animations.sheet;
|
|
107
|
-
const animation = typeof func === "function" ? func(position) : func;
|
|
108
|
-
const type = isDesktop ? _type : forceType ? _type : "sheet";
|
|
109
|
-
const useResizer = type !== "dialog";
|
|
110
|
-
const floating = useFloating({ open, onOpenChange: onChange, strategy: "fixed" });
|
|
111
|
-
const click = useClick(floating.context, {});
|
|
112
|
-
const role = useRole(floating.context, { role: "dialog" });
|
|
113
|
-
const dismiss = useDismiss(floating.context, {
|
|
114
|
-
bubbles: true,
|
|
115
|
-
escapeKey: true,
|
|
116
|
-
outsidePress: (event) => {
|
|
117
|
-
const target = event.target;
|
|
118
|
-
return overlayClickClose && !!target?.isConnected;
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
const interactions = useInteractions([click, dismiss, role].concat(outInteractions));
|
|
122
|
-
const Trigger = trigger;
|
|
123
|
-
const floatingSize = useMotionValue(undefined);
|
|
124
|
-
const sheetY = useMotionValue(undefined);
|
|
125
|
-
const isDragging = useRef(false);
|
|
126
|
-
const dragStart = useRef(0);
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
floatingSize.set(undefined);
|
|
129
|
-
sheetY.set(undefined);
|
|
130
|
-
}, [type, floatingSize, sheetY]);
|
|
131
|
-
const onClose = () => onChange(false);
|
|
132
|
-
useImperativeHandle(externalRef, () => ({ context: floating.context, floating: removeScrollRef.current }), [
|
|
133
|
-
floating.context,
|
|
134
|
-
removeScrollRef,
|
|
135
|
-
]);
|
|
136
|
-
const onDragHeader = (_, info) => {
|
|
137
|
-
const div = floating.refs.floating.current;
|
|
138
|
-
const rect = div.getBoundingClientRect();
|
|
139
|
-
const v = floatingSize.get() || rect.height;
|
|
140
|
-
const result = Math.abs(v - info.delta.y);
|
|
141
|
-
const max = window.outerHeight;
|
|
142
|
-
const screenHeightToClose = calculateClose(max);
|
|
143
|
-
if (result >= screenHeightToClose)
|
|
144
|
-
return floatingSize.set(result);
|
|
145
|
-
if (document.activeElement instanceof HTMLElement) {
|
|
146
|
-
document.activeElement?.blur();
|
|
147
|
-
}
|
|
148
|
-
onChange?.(false);
|
|
149
|
-
return setTimeout(() => floatingSize.set(undefined), 350);
|
|
150
|
-
};
|
|
151
|
-
const draggableMotionProps = type === "sheet"
|
|
152
|
-
? {
|
|
153
|
-
drag: "y",
|
|
154
|
-
animate: false,
|
|
155
|
-
dragElastic: 0,
|
|
156
|
-
initial: false,
|
|
157
|
-
dragConstraints,
|
|
158
|
-
draggable: true,
|
|
159
|
-
dragListener: true,
|
|
160
|
-
dragMomentum: true,
|
|
161
|
-
onDrag: onDragHeader,
|
|
162
|
-
dragPropagation: true,
|
|
163
|
-
dragSnapToOrigin: true,
|
|
164
|
-
dragDirectionLock: true,
|
|
165
|
-
whileDrag: { cursor: "grabbing" },
|
|
166
|
-
}
|
|
167
|
-
: { animate: animated, initial: false };
|
|
168
|
-
const scrollInitial = useMotionValue(undefined);
|
|
169
|
-
const scroll = useMotionValue(undefined);
|
|
170
|
-
const Component = asChild ? Slot : motion.button;
|
|
171
|
-
return (<Fragment>
|
|
172
|
-
{trigger ? (<Component ref={floating.refs.setReference} {...interactions.getReferenceProps()} layoutId={layoutId} type="button">
|
|
173
|
-
{Trigger}
|
|
174
|
-
</Component>) : null}
|
|
175
|
-
<MotionConfig reducedMotion={animated ? "user" : "always"}>
|
|
176
|
-
<FloatingPortal preserveTabOrder root={root}>
|
|
177
|
-
<AnimatePresence mode="wait" propagate>
|
|
178
|
-
{open ? (<FloatingOverlay lockScroll className={css("inset-0 isolate z-overlay flex h-[100dvh] !overflow-clip bg-floating-overlay/80", type === "drawer" ? "" : "items-start justify-center pt-10 lg:p-10", overlayClassName)}>
|
|
179
|
-
<FloatingFocusManager guards modal closeOnFocusOut={closeOnFocusOut} context={floating.context}>
|
|
180
|
-
<AnimatePresence propagate>
|
|
181
|
-
<motion.div {...props} {...(title
|
|
182
|
-
? {
|
|
183
|
-
"aria-labelledby": headingId,
|
|
184
|
-
"aria-describedby": descriptionId,
|
|
185
|
-
}
|
|
186
|
-
: { "aria-label": ariaTitle })} {...interactions.getFloatingProps({
|
|
187
|
-
"aria-modal": open,
|
|
188
|
-
ref: mergeRefs(floating.refs.setFloating, removeScrollRef),
|
|
189
|
-
className: css(variants({ position, type }), className, "isolate overscroll-contain"),
|
|
190
|
-
})} exit="exit" layout={true} animate="enter" initial="initial" layoutId={layoutId} variants={animation} data-component="modal" style={type === "drawer" ? { width: floatingSize } : { height: floatingSize, y: sheetY }}>
|
|
191
|
-
{useResizer && resizer ? (<Draggable onChange={onChange} value={floatingSize} sheet={type === "sheet"} position={position} parent={floating.refs.floating}/>) : null}
|
|
192
|
-
{title ? (<motion.header {...draggableMotionProps} className="relative isolate w-full">
|
|
193
|
-
{title ? (<h2 id={headingId} className="block select-text border-b border-floating-border px-8 pb-2 text-3xl font-medium leading-relaxed">
|
|
194
|
-
{title}
|
|
195
|
-
</h2>) : null}
|
|
196
|
-
</motion.header>) : null}
|
|
197
|
-
<motion.section ref={innerContent} data-component="modal-body" className={css("flex-1 select-text overflow-y-auto px-8 py-1", bodyClassName)} onTouchEnd={async () => {
|
|
198
|
-
scroll.set(undefined);
|
|
199
|
-
scrollInitial.set(undefined);
|
|
200
|
-
if (isDragging.current) {
|
|
201
|
-
const currentY = sheetY.get() || 0;
|
|
202
|
-
const threshold = window.innerHeight * 0.2;
|
|
203
|
-
if (currentY > threshold) {
|
|
204
|
-
await animate(sheetY, window.innerHeight, { duration: 0.2, ease: "easeIn" })
|
|
205
|
-
.finished;
|
|
206
|
-
onChange(false);
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
animate(sheetY, 0, { type: "spring", bounce: 0, duration: 0.3 });
|
|
210
|
-
}
|
|
211
|
-
isDragging.current = false;
|
|
212
|
-
}
|
|
213
|
-
}} onTouchStart={(e) => {
|
|
214
|
-
const touch = e.changedTouches[0];
|
|
215
|
-
scrollInitial.set(touch.pageY);
|
|
216
|
-
scroll.set(touch.pageY);
|
|
217
|
-
isDragging.current = false;
|
|
218
|
-
}} onTouchMove={(e) => {
|
|
219
|
-
const touch = e.changedTouches[0];
|
|
220
|
-
const y = touch.pageY;
|
|
221
|
-
const prevY = scroll.get() || y;
|
|
222
|
-
const scrollTop = innerContent.current?.scrollTop || 0;
|
|
223
|
-
if (!isDragging.current && scrollTop <= 0 && y > prevY && type === "sheet") {
|
|
224
|
-
isDragging.current = true;
|
|
225
|
-
dragStart.current = y;
|
|
226
|
-
}
|
|
227
|
-
if (isDragging.current) {
|
|
228
|
-
const delta = y - dragStart.current;
|
|
229
|
-
if (delta < 0) {
|
|
230
|
-
sheetY.set(delta * 0.2);
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
sheetY.set(delta);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
scroll.set(y);
|
|
237
|
-
}}>
|
|
238
|
-
{children}
|
|
239
|
-
</motion.section>
|
|
240
|
-
{footer ? (<footer className="w-full select-text border-t border-floating-border px-8 pt-4">{footer}</footer>) : null}
|
|
241
|
-
{closable ? (<nav className="absolute right-4 top-1 z-floating">
|
|
242
|
-
<button type="button" onClick={onClose} className="p-1 opacity-70 transition-colors hover:text-danger hover:opacity-100 focus:text-danger">
|
|
243
|
-
<XIcon />
|
|
244
|
-
</button>
|
|
245
|
-
</nav>) : null}
|
|
246
|
-
</motion.div>
|
|
247
|
-
</AnimatePresence>
|
|
248
|
-
</FloatingFocusManager>
|
|
249
|
-
</FloatingOverlay>) : null}
|
|
250
|
-
</AnimatePresence>
|
|
251
|
-
</FloatingPortal>
|
|
252
|
-
</MotionConfig>
|
|
253
|
-
</Fragment>);
|
|
254
|
-
});
|
|
255
|
-
let confirmGlobal = async (options) => {
|
|
256
|
-
if (typeof window !== "undefined") {
|
|
257
|
-
console.warn("ConfirmationProvider is not mounted");
|
|
258
|
-
}
|
|
259
|
-
return false;
|
|
260
|
-
};
|
|
261
|
-
Modal.confirm = (options) => confirmGlobal(options);
|
|
262
|
-
export const ModalConfirmProvider = ({ children }) => {
|
|
263
|
-
const [open, setOpen] = useState(false);
|
|
264
|
-
const [options, setOptions] = useState({});
|
|
265
|
-
const [resolve, setResolve] = useState(() => { });
|
|
266
|
-
const confirmAction = useCallback((opts) => {
|
|
267
|
-
setOptions(opts);
|
|
268
|
-
setOpen(true);
|
|
269
|
-
return new Promise((res) => {
|
|
270
|
-
setResolve(() => res);
|
|
271
|
-
});
|
|
272
|
-
}, []);
|
|
273
|
-
useEffect(() => {
|
|
274
|
-
confirmGlobal = confirmAction;
|
|
275
|
-
}, [confirmAction]);
|
|
276
|
-
const onConfirm = () => {
|
|
277
|
-
setOpen(false);
|
|
278
|
-
const value = options.confirm?.value ?? true;
|
|
279
|
-
resolve(value ?? true);
|
|
280
|
-
};
|
|
281
|
-
const onCancel = () => {
|
|
282
|
-
setOpen(false);
|
|
283
|
-
const value = options.cancel?.value ?? false;
|
|
284
|
-
resolve(value ?? false);
|
|
285
|
-
};
|
|
286
|
-
return (<ConfirmContext.Provider value={confirmAction}>
|
|
287
|
-
{children}
|
|
288
|
-
<Modal open={open} type="dialog" closable={false} onChange={setOpen} overlayClickClose={false} title={options.title || "Confirmation"} className="container max-w-dialog lg:max-w-96" footer={<div className="flex justify-end gap-2">
|
|
289
|
-
<Button theme={options.cancel?.theme || "ghost-muted"} onClick={onCancel}>
|
|
290
|
-
{options.cancel?.text || "Cancel"}
|
|
291
|
-
</Button>
|
|
292
|
-
<Button theme={options.confirm?.theme || "primary"} onClick={onConfirm}>
|
|
293
|
-
{options.confirm?.text || "Confirm"}
|
|
294
|
-
</Button>
|
|
295
|
-
</div>}>
|
|
296
|
-
<div className="py-2 text-foreground">{options.description}</div>
|
|
297
|
-
</Modal>
|
|
298
|
-
</ConfirmContext.Provider>);
|
|
299
|
-
};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { arrow, autoPlacement, autoUpdate, flip, FloatingArrow, FloatingPortal, offset, safePolygon, shift, useClick, useClientPoint, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole, } from "@floating-ui/react";
|
|
3
|
-
import React, { forwardRef, Fragment, useEffect, useRef, useState } from "react";
|
|
4
|
-
import { Polymorph } from "../../components/core/polymorph";
|
|
5
|
-
import { FLOATING_DELAY } from "../../constants";
|
|
6
|
-
import { mergeRefs } from "../../lib/dom";
|
|
7
|
-
import { noop } from "../../lib/fns";
|
|
8
|
-
export const Tooltip = forwardRef(function Tooltip({ as, open, title, children, placement, focus = true, hover = true, enabled = true, popover = true, onChange = noop, followCursor = false, ...props }, outerRef) {
|
|
9
|
-
const [innerOpen, setInnerOpen] = useState(open ?? false);
|
|
10
|
-
const arrowRef = useRef(null);
|
|
11
|
-
const Component = as || "span";
|
|
12
|
-
const toggleBoth = (b) => {
|
|
13
|
-
setInnerOpen(b);
|
|
14
|
-
onChange?.(b);
|
|
15
|
-
};
|
|
16
|
-
const { refs, floatingStyles, context } = useFloating({
|
|
17
|
-
placement,
|
|
18
|
-
open: innerOpen,
|
|
19
|
-
whileElementsMounted: autoUpdate,
|
|
20
|
-
onOpenChange: open ? undefined : toggleBoth,
|
|
21
|
-
middleware: [shift(), offset(5), autoPlacement(), arrow({ padding: 5, element: arrowRef }), flip({ fallbackAxisSideDirection: "start" })],
|
|
22
|
-
});
|
|
23
|
-
const dismiss = useDismiss(context, { enabled });
|
|
24
|
-
const role = useRole(context, { role: "tooltip", enabled });
|
|
25
|
-
const focusController = useFocus(context, { enabled: enabled ? focus : false });
|
|
26
|
-
const clickController = useClick(context, { enabled: enabled ? popover : false });
|
|
27
|
-
const clientPoint = useClientPoint(context, { enabled: !!enabled && !!followCursor });
|
|
28
|
-
const hoverController = useHover(context, {
|
|
29
|
-
move: true,
|
|
30
|
-
delay: { open: FLOATING_DELAY },
|
|
31
|
-
enabled: enabled ? hover : false,
|
|
32
|
-
handleClose: popover ? safePolygon() : null,
|
|
33
|
-
});
|
|
34
|
-
const { getReferenceProps, getFloatingProps } = useInteractions([
|
|
35
|
-
role,
|
|
36
|
-
dismiss,
|
|
37
|
-
clientPoint,
|
|
38
|
-
focus ? focusController : undefined,
|
|
39
|
-
hover ? hoverController : undefined,
|
|
40
|
-
popover ? clickController : undefined,
|
|
41
|
-
]);
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
if (open === undefined)
|
|
44
|
-
return setInnerOpen(false);
|
|
45
|
-
return setInnerOpen(open);
|
|
46
|
-
}, [open]);
|
|
47
|
-
return (<Fragment>
|
|
48
|
-
<Component {...getReferenceProps(props)} ref={mergeRefs(refs.setReference, outerRef)}>
|
|
49
|
-
{title}
|
|
50
|
-
</Component>
|
|
51
|
-
{innerOpen && (<FloatingPortal>
|
|
52
|
-
<Polymorph {...getFloatingProps()} ref={refs.setFloating} style={floatingStyles} className="isolate z-tooltip rounded-lg border border-tooltip-border bg-tooltip-background p-3 text-tooltip-foreground shadow-shadow-floating">
|
|
53
|
-
<FloatingArrow ref={arrowRef} context={context} strokeWidth={0.1} className="fill-tooltip-background stroke-tooltip-border"/>
|
|
54
|
-
{children}
|
|
55
|
-
</Polymorph>
|
|
56
|
-
</FloatingPortal>)}
|
|
57
|
-
</Fragment>);
|
|
58
|
-
});
|