@pk-design/react-tailwind 1.13.2 → 1.14.0
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/cjs/components/Drawer/Drawer.js +2 -80
- package/dist/cjs/components/Drawer/Drawer.js.map +1 -1
- package/dist/cjs/hooks/use-close-on-back.js +86 -0
- package/dist/cjs/hooks/use-close-on-back.js.map +1 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/components/Drawer/Drawer.js +1 -79
- package/dist/es/components/Drawer/Drawer.js.map +1 -1
- package/dist/es/hooks/use-close-on-back.js +84 -0
- package/dist/es/hooks/use-close-on-back.js.map +1 -0
- package/dist/es/index.js +1 -0
- package/dist/es/index.js.map +1 -1
- package/dist/react-tailwind.cjs.js +81 -79
- package/dist/react-tailwind.cjs.js.map +1 -1
- package/dist/react-tailwind.es.js +81 -80
- package/dist/react-tailwind.es.js.map +1 -1
- package/dist/types/hooks/use-close-on-back.d.ts +8 -0
- package/dist/types/hooks/use-close-on-back.test.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-close-on-back.js","sources":["../../../../src/hooks/use-close-on-back.ts"],"sourcesContent":["import React from 'react'\n\n// history.back() lands later, so a drawer opening meanwhile (one replacing another,\n// or React re-running effects under StrictMode) would have its new entry removed\n// instead, and close at once. Removals are counted, and an opening drawer waits for them.\nlet pendingBacks = 0\nconst afterBacks: Array<() => void> = []\n\nfunction settleBack() {\n pendingBacks = Math.max(0, pendingBacks - 1)\n if (pendingBacks === 0) afterBacks.splice(0).forEach((run) => run())\n}\n\nfunction removeEntry() {\n pendingBacks += 1\n let settled = false\n const settle = () => {\n if (settled) return\n settled = true\n window.removeEventListener('popstate', settle)\n settleBack()\n }\n window.addEventListener('popstate', settle)\n // A back that never reports (nothing to go back to) mustn't hold others up.\n window.setTimeout(settle, 500)\n window.history.back()\n}\n\n/**\n * While `active`, the browser's back button (and Android's back gesture)\n * closes the drawer instead of leaving the page: opening adds a history entry\n * (keeping the current state, so routers see the same location), and back\n * removes it. Closed any other way, the entry is removed too, but only if it's\n * still the latest one, so a form that saves and then navigates isn't undone.\n */\nexport function useCloseOnBack(active: boolean, onClose: () => void) {\n const onCloseRef = React.useRef(onClose)\n React.useEffect(() => {\n onCloseRef.current = onClose\n })\n const token = React.useId()\n\n React.useEffect(() => {\n if (!active || typeof window === 'undefined') return\n const pushEntry = () =>\n window.history.pushState({ ...(window.history.state ?? {}), drawer: token }, '')\n let entryPresent = false\n let disposed = false\n const handlePop = () => {\n if (window.history.state?.drawer === token) return\n entryPresent = false\n onCloseRef.current()\n // onClose may step back within the drawer instead of closing it; if it's\n // still open afterwards, take back its entry so the next back works too.\n window.setTimeout(() => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n }, 0)\n }\n const start = () => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n window.addEventListener('popstate', handlePop)\n }\n if (pendingBacks > 0) afterBacks.push(start)\n else start()\n return () => {\n disposed = true\n window.removeEventListener('popstate', handlePop)\n if (entryPresent && window.history.state?.drawer === token) removeEntry()\n }\n }, [active, token])\n}\n"],"names":["React"],"mappings":"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"}
|
package/dist/es/index.js
CHANGED
|
@@ -57,6 +57,7 @@ export { ToastProvider, useToast } from './components/Toast/ToastProvider.js';
|
|
|
57
57
|
export { Toast } from './components/Toast/Toast.js';
|
|
58
58
|
export { VirtualizedDataTable } from './components/VirtualizedDataTable/VirtualizedDataTable.js';
|
|
59
59
|
export { BREAKPOINT_QUERIES, useBreakpoint, useMediaQuery, useResponsiveValue } from './hooks/use-breakpoint.js';
|
|
60
|
+
export { useCloseOnBack } from './hooks/use-close-on-back.js';
|
|
60
61
|
export { useDebounce, useDebounceFn } from './hooks/use-debounce.js';
|
|
61
62
|
export { useIsMobile } from './hooks/use-is-mobile.js';
|
|
62
63
|
export { useIsTablet } from './hooks/use-is-tablet.js';
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -400,6 +400,86 @@ const useResponsiveValue = (value) => {
|
|
|
400
400
|
return value.base;
|
|
401
401
|
};
|
|
402
402
|
|
|
403
|
+
// history.back() lands later, so a drawer opening meanwhile (one replacing another,
|
|
404
|
+
// or React re-running effects under StrictMode) would have its new entry removed
|
|
405
|
+
// instead, and close at once. Removals are counted, and an opening drawer waits for them.
|
|
406
|
+
let pendingBacks = 0;
|
|
407
|
+
const afterBacks = [];
|
|
408
|
+
function settleBack() {
|
|
409
|
+
pendingBacks = Math.max(0, pendingBacks - 1);
|
|
410
|
+
if (pendingBacks === 0)
|
|
411
|
+
afterBacks.splice(0).forEach((run) => run());
|
|
412
|
+
}
|
|
413
|
+
function removeEntry() {
|
|
414
|
+
pendingBacks += 1;
|
|
415
|
+
let settled = false;
|
|
416
|
+
const settle = () => {
|
|
417
|
+
if (settled)
|
|
418
|
+
return;
|
|
419
|
+
settled = true;
|
|
420
|
+
window.removeEventListener('popstate', settle);
|
|
421
|
+
settleBack();
|
|
422
|
+
};
|
|
423
|
+
window.addEventListener('popstate', settle);
|
|
424
|
+
// A back that never reports (nothing to go back to) mustn't hold others up.
|
|
425
|
+
window.setTimeout(settle, 500);
|
|
426
|
+
window.history.back();
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* While `active`, the browser's back button (and Android's back gesture)
|
|
430
|
+
* closes the drawer instead of leaving the page: opening adds a history entry
|
|
431
|
+
* (keeping the current state, so routers see the same location), and back
|
|
432
|
+
* removes it. Closed any other way, the entry is removed too, but only if it's
|
|
433
|
+
* still the latest one, so a form that saves and then navigates isn't undone.
|
|
434
|
+
*/
|
|
435
|
+
function useCloseOnBack(active, onClose) {
|
|
436
|
+
const onCloseRef = React.useRef(onClose);
|
|
437
|
+
React.useEffect(() => {
|
|
438
|
+
onCloseRef.current = onClose;
|
|
439
|
+
});
|
|
440
|
+
const token = React.useId();
|
|
441
|
+
React.useEffect(() => {
|
|
442
|
+
if (!active || typeof window === 'undefined')
|
|
443
|
+
return;
|
|
444
|
+
const pushEntry = () => { var _a; return window.history.pushState({ ...((_a = window.history.state) !== null && _a !== void 0 ? _a : {}), drawer: token }, ''); };
|
|
445
|
+
let entryPresent = false;
|
|
446
|
+
let disposed = false;
|
|
447
|
+
const handlePop = () => {
|
|
448
|
+
var _a;
|
|
449
|
+
if (((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
|
|
450
|
+
return;
|
|
451
|
+
entryPresent = false;
|
|
452
|
+
onCloseRef.current();
|
|
453
|
+
// onClose may step back within the drawer instead of closing it; if it's
|
|
454
|
+
// still open afterwards, take back its entry so the next back works too.
|
|
455
|
+
window.setTimeout(() => {
|
|
456
|
+
if (disposed)
|
|
457
|
+
return;
|
|
458
|
+
pushEntry();
|
|
459
|
+
entryPresent = true;
|
|
460
|
+
}, 0);
|
|
461
|
+
};
|
|
462
|
+
const start = () => {
|
|
463
|
+
if (disposed)
|
|
464
|
+
return;
|
|
465
|
+
pushEntry();
|
|
466
|
+
entryPresent = true;
|
|
467
|
+
window.addEventListener('popstate', handlePop);
|
|
468
|
+
};
|
|
469
|
+
if (pendingBacks > 0)
|
|
470
|
+
afterBacks.push(start);
|
|
471
|
+
else
|
|
472
|
+
start();
|
|
473
|
+
return () => {
|
|
474
|
+
var _a;
|
|
475
|
+
disposed = true;
|
|
476
|
+
window.removeEventListener('popstate', handlePop);
|
|
477
|
+
if (entryPresent && ((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
|
|
478
|
+
removeEntry();
|
|
479
|
+
};
|
|
480
|
+
}, [active, token]);
|
|
481
|
+
}
|
|
482
|
+
|
|
403
483
|
const alignmentMap = {
|
|
404
484
|
center: 'items-center justify-center h-full',
|
|
405
485
|
start: 'justify-start h-full',
|
|
@@ -498,85 +578,6 @@ const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align
|
|
|
498
578
|
: [panelAlignmentMap[align], panelSizeMap[size], panelClass])), "data-layout": fullscreen ? 'fullscreen' : undefined, children: [shouldShowDragHandle && (jsxRuntime.jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab", "data-testid": "drawer-drag-handle" })), fullscreen && (jsxRuntime.jsxs("div", { className: "sticky top-0 z-10 flex h-14 shrink-0 items-center gap-1 border-b border-[var(--ui-border)] bg-white pl-1 pr-3 pt-[env(safe-area-inset-top,0px)] box-content dark:bg-gray-800", children: [jsxRuntime.jsx(Button, { iconOnly: true, "aria-label": "Close", variant: "plain", theme: "secondary", onClick: onClose, className: "shrink-0", children: jsxRuntime.jsx(SvgX, { className: "size-5" }) }), title && (jsxRuntime.jsx(react.DialogTitle, { as: "h3", className: "min-w-0 flex-1 truncate text-base font-semibold text-gray-900 dark:text-white", children: title })), headerAction && jsxRuntime.jsx("div", { className: "ml-auto shrink-0", children: headerAction })] })), !fullscreen && showTitleSection && (jsxRuntime.jsxs("div", { className: buildClassName('space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsxRuntime.jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsxRuntime.jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsxRuntime.jsx(react.DialogTitle, { as: "h3", className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0', titleClass), children: title }))] }), showCloseButton && (jsxRuntime.jsx(Button, { iconOnly: true, "aria-label": "Close drawer", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsxRuntime.jsx(SvgX, { className: "size-4" }) }))] }), description && (jsxRuntime.jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsxRuntime.jsxs("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass, fullscreen && 'pb-[calc(1rem+env(safe-area-inset-bottom,0px))]'), children: [fullscreen && description && (jsxRuntime.jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400', descriptionClass), children: description })), children] }), !fullscreen && footer && (jsxRuntime.jsx("div", { className: buildClassName('p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0', footerSticky && 'sticky bottom-0 z-10'), children: footer }))] }) }) })] }));
|
|
499
579
|
};
|
|
500
580
|
Drawer.displayName = 'Drawer';
|
|
501
|
-
// history.back() lands later, so a drawer opening meanwhile (one replacing another,
|
|
502
|
-
// or React re-running effects under StrictMode) would have its new entry removed
|
|
503
|
-
// instead, and close at once. Removals are counted, and an opening drawer waits for them.
|
|
504
|
-
let pendingBacks = 0;
|
|
505
|
-
const afterBacks = [];
|
|
506
|
-
function settleBack() {
|
|
507
|
-
pendingBacks = Math.max(0, pendingBacks - 1);
|
|
508
|
-
if (pendingBacks === 0)
|
|
509
|
-
afterBacks.splice(0).forEach((run) => run());
|
|
510
|
-
}
|
|
511
|
-
function removeEntry() {
|
|
512
|
-
pendingBacks += 1;
|
|
513
|
-
let settled = false;
|
|
514
|
-
const settle = () => {
|
|
515
|
-
if (settled)
|
|
516
|
-
return;
|
|
517
|
-
settled = true;
|
|
518
|
-
window.removeEventListener('popstate', settle);
|
|
519
|
-
settleBack();
|
|
520
|
-
};
|
|
521
|
-
window.addEventListener('popstate', settle);
|
|
522
|
-
// A back that never reports (nothing to go back to) mustn't hold others up.
|
|
523
|
-
window.setTimeout(settle, 500);
|
|
524
|
-
window.history.back();
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* While `active`, the browser's back button (and Android's back gesture)
|
|
528
|
-
* closes the drawer instead of leaving the page: opening adds a history entry
|
|
529
|
-
* (keeping the current state, so routers see the same location), and back
|
|
530
|
-
* removes it. Closed any other way, the entry is removed too, but only if it's
|
|
531
|
-
* still the latest one, so a form that saves and then navigates isn't undone.
|
|
532
|
-
*/
|
|
533
|
-
function useCloseOnBack(active, onClose) {
|
|
534
|
-
const onCloseRef = React.useRef(onClose);
|
|
535
|
-
React.useEffect(() => {
|
|
536
|
-
onCloseRef.current = onClose;
|
|
537
|
-
});
|
|
538
|
-
const token = React.useId();
|
|
539
|
-
React.useEffect(() => {
|
|
540
|
-
if (!active || typeof window === 'undefined')
|
|
541
|
-
return;
|
|
542
|
-
const pushEntry = () => { var _a; return window.history.pushState({ ...((_a = window.history.state) !== null && _a !== void 0 ? _a : {}), drawer: token }, ''); };
|
|
543
|
-
let entryPresent = false;
|
|
544
|
-
let disposed = false;
|
|
545
|
-
const handlePop = () => {
|
|
546
|
-
var _a;
|
|
547
|
-
if (((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
|
|
548
|
-
return;
|
|
549
|
-
entryPresent = false;
|
|
550
|
-
onCloseRef.current();
|
|
551
|
-
// onClose may step back within the drawer instead of closing it; if it's
|
|
552
|
-
// still open afterwards, take back its entry so the next back works too.
|
|
553
|
-
window.setTimeout(() => {
|
|
554
|
-
if (disposed)
|
|
555
|
-
return;
|
|
556
|
-
pushEntry();
|
|
557
|
-
entryPresent = true;
|
|
558
|
-
}, 0);
|
|
559
|
-
};
|
|
560
|
-
const start = () => {
|
|
561
|
-
if (disposed)
|
|
562
|
-
return;
|
|
563
|
-
pushEntry();
|
|
564
|
-
entryPresent = true;
|
|
565
|
-
window.addEventListener('popstate', handlePop);
|
|
566
|
-
};
|
|
567
|
-
if (pendingBacks > 0)
|
|
568
|
-
afterBacks.push(start);
|
|
569
|
-
else
|
|
570
|
-
start();
|
|
571
|
-
return () => {
|
|
572
|
-
var _a;
|
|
573
|
-
disposed = true;
|
|
574
|
-
window.removeEventListener('popstate', handlePop);
|
|
575
|
-
if (entryPresent && ((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
|
|
576
|
-
removeEntry();
|
|
577
|
-
};
|
|
578
|
-
}, [active, token]);
|
|
579
|
-
}
|
|
580
581
|
|
|
581
582
|
function ActionSheet({ isOpen, onClose, title, description, actions, showCancelButton = true, cancelLabel = 'Cancel', onCancel, closeOnBackdropClick = true, dragHandle = true, panelClass = '', containerClass = '', }) {
|
|
582
583
|
const handleItemClick = (action) => {
|
|
@@ -5352,6 +5353,7 @@ exports.isEmpty = isEmpty;
|
|
|
5352
5353
|
exports.nextSortDirection = nextSortDirection;
|
|
5353
5354
|
exports.updateSortQuery = updateSortQuery;
|
|
5354
5355
|
exports.useBreakpoint = useBreakpoint;
|
|
5356
|
+
exports.useCloseOnBack = useCloseOnBack;
|
|
5355
5357
|
exports.useDebounce = useDebounce;
|
|
5356
5358
|
exports.useDebounceFn = useDebounceFn;
|
|
5357
5359
|
exports.useIsMobile = useIsMobile;
|