@jinaan/uikit 0.1.9 → 0.1.10
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/choice-dialog.d.ts.map +1 -1
- package/dist/dialog.d.ts +3 -0
- package/dist/dialog.d.ts.map +1 -1
- package/dist/index.js +560 -557
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/choice-dialog.tsx +2 -7
- package/src/dialog.tsx +48 -13
package/package.json
CHANGED
package/src/choice-dialog.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { Button } from "./button";
|
|
|
4
4
|
import {
|
|
5
5
|
Dialog,
|
|
6
6
|
DialogBody,
|
|
7
|
+
DialogCancel,
|
|
7
8
|
DialogContent,
|
|
8
9
|
DialogFooter,
|
|
9
10
|
DialogHeader,
|
|
@@ -93,13 +94,7 @@ export function ChoiceDialog({
|
|
|
93
94
|
</DialogBody>
|
|
94
95
|
</DialogPanel>
|
|
95
96
|
<DialogFooter className="gap-3 pt-2.5">
|
|
96
|
-
<
|
|
97
|
-
variant="secondary"
|
|
98
|
-
className="flex-1"
|
|
99
|
-
onClick={() => onOpenChange?.(false)}
|
|
100
|
-
>
|
|
101
|
-
{cancelLabel}
|
|
102
|
-
</Button>
|
|
97
|
+
<DialogCancel className="flex-1">{cancelLabel}</DialogCancel>
|
|
103
98
|
<Button className="flex-1" onClick={() => onConfirm?.(selected)}>
|
|
104
99
|
{confirmLabel}
|
|
105
100
|
</Button>
|
package/src/dialog.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
type HTMLAttributes,
|
|
14
14
|
} from "react";
|
|
15
15
|
|
|
16
|
+
import { Button, type ButtonProps } from "./button";
|
|
16
17
|
import { computeDialogFlight, type DialogOriginRect } from "./dialog-motion";
|
|
17
18
|
import { cn } from "./utils";
|
|
18
19
|
|
|
@@ -81,6 +82,7 @@ function resolveOrigin(content: HTMLElement): DialogOriginRect | null {
|
|
|
81
82
|
|
|
82
83
|
const DIALOG_CLOSE_MS = 250;
|
|
83
84
|
const DialogClosingContext = createContext(false);
|
|
85
|
+
const DialogRequestCloseContext = createContext<() => void>(() => {});
|
|
84
86
|
|
|
85
87
|
/** Dialog root; owns the delayed close so the fly-out can finish. */
|
|
86
88
|
export function Dialog({
|
|
@@ -94,6 +96,7 @@ export function Dialog({
|
|
|
94
96
|
defaultOpen ?? false,
|
|
95
97
|
);
|
|
96
98
|
const [closing, setClosing] = useState(false);
|
|
99
|
+
const closingRef = useRef(false);
|
|
97
100
|
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
98
101
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
99
102
|
const openRef = useRef(open);
|
|
@@ -116,12 +119,13 @@ export function Dialog({
|
|
|
116
119
|
const handleOpenChange = (next: boolean) => {
|
|
117
120
|
if (next) {
|
|
118
121
|
if (closeTimer.current) clearTimeout(closeTimer.current);
|
|
122
|
+
closingRef.current = false;
|
|
119
123
|
setClosing(false);
|
|
120
124
|
if (!controlled) setUncontrolledOpen(true);
|
|
121
125
|
onOpenChange?.(true);
|
|
122
126
|
return;
|
|
123
127
|
}
|
|
124
|
-
if (!open ||
|
|
128
|
+
if (!open || closingRef.current) return;
|
|
125
129
|
|
|
126
130
|
const reduced =
|
|
127
131
|
typeof window !== "undefined" &&
|
|
@@ -133,27 +137,33 @@ export function Dialog({
|
|
|
133
137
|
return;
|
|
134
138
|
}
|
|
135
139
|
|
|
140
|
+
closingRef.current = true;
|
|
136
141
|
setClosing(true);
|
|
137
142
|
closeTimer.current = setTimeout(() => {
|
|
138
143
|
if (!controlled) setUncontrolledOpen(false);
|
|
139
144
|
onOpenChange?.(false);
|
|
140
145
|
requestAnimationFrame(() => {
|
|
141
146
|
// Restore the overlay only when a controlled parent vetoed the close.
|
|
142
|
-
if (openRef.current)
|
|
147
|
+
if (openRef.current) {
|
|
148
|
+
closingRef.current = false;
|
|
149
|
+
setClosing(false);
|
|
150
|
+
}
|
|
143
151
|
});
|
|
144
152
|
}, DIALOG_CLOSE_MS);
|
|
145
153
|
};
|
|
146
154
|
|
|
147
155
|
return (
|
|
148
|
-
<
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
<DialogRequestCloseContext.Provider value={() => handleOpenChange(false)}>
|
|
157
|
+
<DialogClosingContext.Provider value={closing}>
|
|
158
|
+
<DialogPrimitive.Root
|
|
159
|
+
open={open}
|
|
160
|
+
onOpenChange={handleOpenChange}
|
|
161
|
+
{...props}
|
|
162
|
+
>
|
|
163
|
+
{children}
|
|
164
|
+
</DialogPrimitive.Root>
|
|
165
|
+
</DialogClosingContext.Provider>
|
|
166
|
+
</DialogRequestCloseContext.Provider>
|
|
157
167
|
);
|
|
158
168
|
}
|
|
159
169
|
|
|
@@ -174,6 +184,18 @@ DialogTrigger.displayName = "DialogTrigger";
|
|
|
174
184
|
|
|
175
185
|
export const DialogClose = DialogPrimitive.Close;
|
|
176
186
|
|
|
187
|
+
/** Secondary action that closes through the animated dialog close path. */
|
|
188
|
+
export const DialogCancel = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
189
|
+
({ variant = "secondary", children = "Cancel", ...props }, ref) => (
|
|
190
|
+
<DialogPrimitive.Close asChild>
|
|
191
|
+
<Button ref={ref} type="button" variant={variant} {...props}>
|
|
192
|
+
{children}
|
|
193
|
+
</Button>
|
|
194
|
+
</DialogPrimitive.Close>
|
|
195
|
+
),
|
|
196
|
+
);
|
|
197
|
+
DialogCancel.displayName = "DialogCancel";
|
|
198
|
+
|
|
177
199
|
function startDialogMotion(content: HTMLDivElement, retry = true) {
|
|
178
200
|
if (content.dataset.dialogMotionStarted === "true") return;
|
|
179
201
|
if (
|
|
@@ -229,8 +251,9 @@ function startDialogMotion(content: HTMLDivElement, retry = true) {
|
|
|
229
251
|
export const DialogContent = forwardRef<
|
|
230
252
|
ElementRef<typeof DialogPrimitive.Content>,
|
|
231
253
|
ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
|
232
|
-
>(({ className, children, ...props }, ref) => {
|
|
254
|
+
>(({ className, children, onEscapeKeyDown, onPointerDownOutside, ...props }, ref) => {
|
|
233
255
|
const closing = useContext(DialogClosingContext);
|
|
256
|
+
const requestClose = useContext(DialogRequestCloseContext);
|
|
234
257
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
235
258
|
const setRef = useCallback(
|
|
236
259
|
(node: HTMLDivElement | null) => {
|
|
@@ -251,7 +274,7 @@ export const DialogContent = forwardRef<
|
|
|
251
274
|
<DialogPrimitive.Portal>
|
|
252
275
|
<DialogPrimitive.Overlay
|
|
253
276
|
className={cn(
|
|
254
|
-
"fixed inset-0 z-50 overflow-hidden bg-overlay data-[state=open]:animate-in data-[state=open]:fade-in-0",
|
|
277
|
+
"fixed inset-0 z-50 overflow-hidden bg-overlay backdrop-blur-[3px] data-[state=open]:animate-in data-[state=open]:fade-in-0",
|
|
255
278
|
!closing &&
|
|
256
279
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
257
280
|
closing && "opacity-0 transition-opacity duration-200",
|
|
@@ -272,6 +295,18 @@ export const DialogContent = forwardRef<
|
|
|
272
295
|
"focus:outline-none",
|
|
273
296
|
className,
|
|
274
297
|
)}
|
|
298
|
+
onEscapeKeyDown={(event) => {
|
|
299
|
+
onEscapeKeyDown?.(event);
|
|
300
|
+
if (event.defaultPrevented) return;
|
|
301
|
+
event.preventDefault();
|
|
302
|
+
requestClose();
|
|
303
|
+
}}
|
|
304
|
+
onPointerDownOutside={(event) => {
|
|
305
|
+
onPointerDownOutside?.(event);
|
|
306
|
+
if (event.defaultPrevented) return;
|
|
307
|
+
event.preventDefault();
|
|
308
|
+
requestClose();
|
|
309
|
+
}}
|
|
275
310
|
{...props}
|
|
276
311
|
>
|
|
277
312
|
{children}
|