@diwauhris/ui 1.7.18 → 1.7.20
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/lib/assets/ui.css +18 -0
- package/lib/index.cjs +185 -9
- package/lib/index.mjs +135 -10
- package/lib/types/ui-library/gallery/application-error/ApplicationError.d.ts +96 -0
- package/lib/types/ui-library/gallery/forbidden-error/ForbiddenError.d.ts +39 -0
- package/lib/types/ui-library/gallery/not-found-error/NotFoundError.d.ts +39 -0
- package/lib/types/ui-library/index.d.ts +6 -0
- package/package.json +1 -1
package/lib/assets/ui.css
CHANGED
|
@@ -809,6 +809,10 @@
|
|
|
809
809
|
max-height: 6rem;
|
|
810
810
|
}
|
|
811
811
|
|
|
812
|
+
.max-h-48 {
|
|
813
|
+
max-height: 12rem;
|
|
814
|
+
}
|
|
815
|
+
|
|
812
816
|
.max-h-60 {
|
|
813
817
|
max-height: 15rem;
|
|
814
818
|
}
|
|
@@ -2899,6 +2903,10 @@
|
|
|
2899
2903
|
background-color: rgb(255 255 255 / 0.75);
|
|
2900
2904
|
}
|
|
2901
2905
|
|
|
2906
|
+
.bg-white\/95 {
|
|
2907
|
+
background-color: rgb(255 255 255 / 0.95);
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2902
2910
|
.bg-gradient-to-r {
|
|
2903
2911
|
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
|
2904
2912
|
}
|
|
@@ -3701,6 +3709,11 @@
|
|
|
3701
3709
|
color: rgb(234 88 12 / var(--tw-text-opacity, 1));
|
|
3702
3710
|
}
|
|
3703
3711
|
|
|
3712
|
+
.text-rose-300 {
|
|
3713
|
+
--tw-text-opacity: 1;
|
|
3714
|
+
color: rgb(253 164 175 / var(--tw-text-opacity, 1));
|
|
3715
|
+
}
|
|
3716
|
+
|
|
3704
3717
|
.text-rose-300\/60 {
|
|
3705
3718
|
color: rgb(253 164 175 / 0.6);
|
|
3706
3719
|
}
|
|
@@ -4121,6 +4134,11 @@
|
|
|
4121
4134
|
--tw-ring-offset-width: 2px;
|
|
4122
4135
|
}
|
|
4123
4136
|
|
|
4137
|
+
.blur {
|
|
4138
|
+
--tw-blur: blur(8px);
|
|
4139
|
+
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
4140
|
+
}
|
|
4141
|
+
|
|
4124
4142
|
.drop-shadow {
|
|
4125
4143
|
--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06));
|
|
4126
4144
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
package/lib/index.cjs
CHANGED
|
@@ -3957,16 +3957,40 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3957
3957
|
const [panelStyle, setPanelStyle] = (0, react.useState)({});
|
|
3958
3958
|
(0, react.useEffect)(() => {
|
|
3959
3959
|
if (!open || !triggerRef.current) return;
|
|
3960
|
-
const
|
|
3960
|
+
const GAP = 4;
|
|
3961
|
+
const MARGIN = 8;
|
|
3961
3962
|
const PANEL_MIN_WIDTH = 176;
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3963
|
+
const ROW_HEIGHT = 36;
|
|
3964
|
+
const HEADER_HEIGHT = 8;
|
|
3965
|
+
const reposition = () => {
|
|
3966
|
+
const trigger = triggerRef.current;
|
|
3967
|
+
if (!trigger) return;
|
|
3968
|
+
const rect = trigger.getBoundingClientRect();
|
|
3969
|
+
const panelHeight = panelRef.current?.offsetHeight ?? items.length * ROW_HEIGHT + HEADER_HEIGHT;
|
|
3970
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3971
|
+
const flipUp = spaceBelow < panelHeight + GAP + MARGIN && rect.top > spaceBelow;
|
|
3972
|
+
setPanelStyle({
|
|
3973
|
+
position: "fixed",
|
|
3974
|
+
...flipUp ? { bottom: Math.max(MARGIN, window.innerHeight - rect.top + GAP) } : { top: rect.bottom + GAP },
|
|
3975
|
+
left: align === "left" ? rect.left : Math.max(MARGIN, rect.right - PANEL_MIN_WIDTH),
|
|
3976
|
+
zIndex: 9999,
|
|
3977
|
+
minWidth: Math.max(rect.width, PANEL_MIN_WIDTH)
|
|
3978
|
+
});
|
|
3979
|
+
};
|
|
3980
|
+
reposition();
|
|
3981
|
+
const raf = window.requestAnimationFrame(reposition);
|
|
3982
|
+
window.addEventListener("scroll", reposition, true);
|
|
3983
|
+
window.addEventListener("resize", reposition);
|
|
3984
|
+
return () => {
|
|
3985
|
+
window.cancelAnimationFrame(raf);
|
|
3986
|
+
window.removeEventListener("scroll", reposition, true);
|
|
3987
|
+
window.removeEventListener("resize", reposition);
|
|
3988
|
+
};
|
|
3989
|
+
}, [
|
|
3990
|
+
open,
|
|
3991
|
+
align,
|
|
3992
|
+
items.length
|
|
3993
|
+
]);
|
|
3970
3994
|
(0, react.useEffect)(() => {
|
|
3971
3995
|
if (!open) return;
|
|
3972
3996
|
const handlePointerDown = (e) => {
|
|
@@ -4618,6 +4642,154 @@ function StatusPage({ eyebrow, title, description, code, icon, primaryAction, se
|
|
|
4618
4642
|
});
|
|
4619
4643
|
}
|
|
4620
4644
|
//#endregion
|
|
4645
|
+
//#region src/ui-library/gallery/not-found-error/NotFoundError.tsx
|
|
4646
|
+
/**
|
|
4647
|
+
* NotFoundError — Design System Component
|
|
4648
|
+
*
|
|
4649
|
+
* Full-page 404 Not Found screen. Composes StatusPage internally using the
|
|
4650
|
+
* `notFound` preset. Navigation is the consumer's responsibility — wire it
|
|
4651
|
+
* via `primaryAction.onClick` and `secondaryAction.onClick`.
|
|
4652
|
+
*
|
|
4653
|
+
* No routing imports. Works with any router (React Router, Next.js, window.location).
|
|
4654
|
+
*
|
|
4655
|
+
* Usage:
|
|
4656
|
+
* import { NotFoundError } from '@diwauhris/ui';
|
|
4657
|
+
* import { useNavigate } from 'react-router-dom';
|
|
4658
|
+
*
|
|
4659
|
+
* function NotFoundPage() {
|
|
4660
|
+
* const navigate = useNavigate();
|
|
4661
|
+
* return (
|
|
4662
|
+
* <NotFoundError
|
|
4663
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
4664
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
4665
|
+
* />
|
|
4666
|
+
* );
|
|
4667
|
+
* }
|
|
4668
|
+
*/
|
|
4669
|
+
function NotFoundError({ primaryAction, secondaryAction, className }) {
|
|
4670
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPage, {
|
|
4671
|
+
...STATUS_PAGE_PRESETS.notFound,
|
|
4672
|
+
primaryAction,
|
|
4673
|
+
secondaryAction,
|
|
4674
|
+
className
|
|
4675
|
+
});
|
|
4676
|
+
}
|
|
4677
|
+
//#endregion
|
|
4678
|
+
//#region src/ui-library/gallery/forbidden-error/ForbiddenError.tsx
|
|
4679
|
+
/**
|
|
4680
|
+
* ForbiddenError — Design System Component
|
|
4681
|
+
*
|
|
4682
|
+
* Full-page 403 Access Restricted screen. Composes StatusPage internally
|
|
4683
|
+
* using the `forbidden` preset. Navigation is the consumer's responsibility
|
|
4684
|
+
* — wire it via `primaryAction.onClick` and `secondaryAction.onClick`.
|
|
4685
|
+
*
|
|
4686
|
+
* No routing imports. Works with any router (React Router, Next.js, window.location).
|
|
4687
|
+
*
|
|
4688
|
+
* Usage:
|
|
4689
|
+
* import { ForbiddenError } from '@diwauhris/ui';
|
|
4690
|
+
* import { useNavigate } from 'react-router-dom';
|
|
4691
|
+
*
|
|
4692
|
+
* function ForbiddenPage() {
|
|
4693
|
+
* const navigate = useNavigate();
|
|
4694
|
+
* return (
|
|
4695
|
+
* <ForbiddenError
|
|
4696
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
4697
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
4698
|
+
* />
|
|
4699
|
+
* );
|
|
4700
|
+
* }
|
|
4701
|
+
*/
|
|
4702
|
+
function ForbiddenError({ primaryAction, secondaryAction, className }) {
|
|
4703
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPage, {
|
|
4704
|
+
...STATUS_PAGE_PRESETS.forbidden,
|
|
4705
|
+
primaryAction,
|
|
4706
|
+
secondaryAction,
|
|
4707
|
+
className
|
|
4708
|
+
});
|
|
4709
|
+
}
|
|
4710
|
+
//#endregion
|
|
4711
|
+
//#region src/ui-library/gallery/application-error/ApplicationError.tsx
|
|
4712
|
+
/**
|
|
4713
|
+
* ApplicationError — Design System Component
|
|
4714
|
+
*
|
|
4715
|
+
* Full-page 500 / unexpected error screen. Composes StatusPage internally
|
|
4716
|
+
* using the `serverError` preset. Includes a dev-only collapsible details
|
|
4717
|
+
* panel (error message, stack trace, component stack) rendered only when
|
|
4718
|
+
* `import.meta.env.DEV && error !== undefined`.
|
|
4719
|
+
*
|
|
4720
|
+
* Navigation is the consumer's responsibility — wire onRetry and onDashboard.
|
|
4721
|
+
*
|
|
4722
|
+
* Two exports:
|
|
4723
|
+
*
|
|
4724
|
+
* ApplicationError — primary component. Consumer provides both callbacks.
|
|
4725
|
+
* Used as React Router `errorElement` (pair with useRouteError + useNavigate).
|
|
4726
|
+
*
|
|
4727
|
+
* ApplicationErrorFallback — convenience wrapper for ErrorBoundary usage.
|
|
4728
|
+
* Accepts onReset (maps to onRetry) and uses window.location.href for
|
|
4729
|
+
* dashboard navigation when outside router context.
|
|
4730
|
+
*
|
|
4731
|
+
* No routing imports in this file. Works with any router.
|
|
4732
|
+
*
|
|
4733
|
+
* Usage (router errorElement):
|
|
4734
|
+
* import { ApplicationError } from '@diwauhris/ui';
|
|
4735
|
+
* import { useRouteError, useNavigate } from 'react-router-dom';
|
|
4736
|
+
*
|
|
4737
|
+
* export function ErrorPage() {
|
|
4738
|
+
* const error = useRouteError();
|
|
4739
|
+
* const navigate = useNavigate();
|
|
4740
|
+
* return (
|
|
4741
|
+
* <ApplicationError
|
|
4742
|
+
* error={error}
|
|
4743
|
+
* onRetry={() => navigate(0)}
|
|
4744
|
+
* onDashboard={() => navigate('/dashboard')}
|
|
4745
|
+
* />
|
|
4746
|
+
* );
|
|
4747
|
+
* }
|
|
4748
|
+
*
|
|
4749
|
+
* Usage (ErrorBoundary fallback):
|
|
4750
|
+
* import { ApplicationErrorFallback } from '@diwauhris/ui';
|
|
4751
|
+
*
|
|
4752
|
+
* <ErrorBoundary fallbackRender={({ error, resetErrorBoundary }) => (
|
|
4753
|
+
* <ApplicationErrorFallback
|
|
4754
|
+
* error={error}
|
|
4755
|
+
* onReset={resetErrorBoundary}
|
|
4756
|
+
* />
|
|
4757
|
+
* )} />
|
|
4758
|
+
*/
|
|
4759
|
+
function ApplicationError({ error, componentStack, errorId, onRetry, onDashboard, className }) {
|
|
4760
|
+
const showDevDetails = false;
|
|
4761
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4762
|
+
className,
|
|
4763
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPage, {
|
|
4764
|
+
...STATUS_PAGE_PRESETS.serverError,
|
|
4765
|
+
primaryAction: {
|
|
4766
|
+
label: "Try Again",
|
|
4767
|
+
onClick: onRetry
|
|
4768
|
+
},
|
|
4769
|
+
secondaryAction: {
|
|
4770
|
+
label: "Go to Dashboard",
|
|
4771
|
+
onClick: onDashboard
|
|
4772
|
+
}
|
|
4773
|
+
}), showDevDetails]
|
|
4774
|
+
});
|
|
4775
|
+
}
|
|
4776
|
+
/**
|
|
4777
|
+
* Convenience wrapper for use with class-based ErrorBoundary components.
|
|
4778
|
+
* Outside router context — uses window.location.href for dashboard navigation.
|
|
4779
|
+
* Maps `onReset` to ApplicationError's `onRetry`.
|
|
4780
|
+
*/
|
|
4781
|
+
function ApplicationErrorFallback({ error, componentStack, errorId, onReset }) {
|
|
4782
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ApplicationError, {
|
|
4783
|
+
error,
|
|
4784
|
+
componentStack,
|
|
4785
|
+
errorId,
|
|
4786
|
+
onRetry: onReset,
|
|
4787
|
+
onDashboard: () => {
|
|
4788
|
+
window.location.href = "/dashboard";
|
|
4789
|
+
}
|
|
4790
|
+
});
|
|
4791
|
+
}
|
|
4792
|
+
//#endregion
|
|
4621
4793
|
//#region src/ui-library/gallery/employee-card/EmployeeCard.tsx
|
|
4622
4794
|
function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className = "" }) {
|
|
4623
4795
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
@@ -8608,6 +8780,8 @@ exports.AccordionItem = AccordionItem;
|
|
|
8608
8780
|
exports.AccordionTrigger = AccordionTrigger;
|
|
8609
8781
|
exports.ActivityFeed = ActivityFeed;
|
|
8610
8782
|
exports.Alert = Alert;
|
|
8783
|
+
exports.ApplicationError = ApplicationError;
|
|
8784
|
+
exports.ApplicationErrorFallback = ApplicationErrorFallback;
|
|
8611
8785
|
exports.ApprovalTimeline = ApprovalTimeline;
|
|
8612
8786
|
exports.AreaChart = AreaChart;
|
|
8613
8787
|
exports.Avatar = Avatar;
|
|
@@ -8645,6 +8819,7 @@ exports.FieldContext = FieldContext;
|
|
|
8645
8819
|
exports.FieldInput = FieldInput;
|
|
8646
8820
|
exports.FileUpload = FileUpload;
|
|
8647
8821
|
exports.FilterChip = FilterChip;
|
|
8822
|
+
exports.ForbiddenError = ForbiddenError;
|
|
8648
8823
|
exports.Heatmap = Heatmap;
|
|
8649
8824
|
exports.IconButton = IconButton;
|
|
8650
8825
|
exports.Input = Input;
|
|
@@ -8654,6 +8829,7 @@ exports.LineChart = LineChart;
|
|
|
8654
8829
|
exports.MaskedValue = MaskedValue;
|
|
8655
8830
|
exports.Menu = Menu;
|
|
8656
8831
|
exports.Modal = Modal;
|
|
8832
|
+
exports.NotFoundError = NotFoundError;
|
|
8657
8833
|
exports.OrgChart = OrgChart;
|
|
8658
8834
|
exports.OrgUnitTree = OrgUnitTree;
|
|
8659
8835
|
exports.OtpInput = OtpInput;
|
package/lib/index.mjs
CHANGED
|
@@ -3933,16 +3933,40 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3933
3933
|
const [panelStyle, setPanelStyle] = useState({});
|
|
3934
3934
|
useEffect(() => {
|
|
3935
3935
|
if (!open || !triggerRef.current) return;
|
|
3936
|
-
const
|
|
3936
|
+
const GAP = 4;
|
|
3937
|
+
const MARGIN = 8;
|
|
3937
3938
|
const PANEL_MIN_WIDTH = 176;
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3939
|
+
const ROW_HEIGHT = 36;
|
|
3940
|
+
const HEADER_HEIGHT = 8;
|
|
3941
|
+
const reposition = () => {
|
|
3942
|
+
const trigger = triggerRef.current;
|
|
3943
|
+
if (!trigger) return;
|
|
3944
|
+
const rect = trigger.getBoundingClientRect();
|
|
3945
|
+
const panelHeight = panelRef.current?.offsetHeight ?? items.length * ROW_HEIGHT + HEADER_HEIGHT;
|
|
3946
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3947
|
+
const flipUp = spaceBelow < panelHeight + GAP + MARGIN && rect.top > spaceBelow;
|
|
3948
|
+
setPanelStyle({
|
|
3949
|
+
position: "fixed",
|
|
3950
|
+
...flipUp ? { bottom: Math.max(MARGIN, window.innerHeight - rect.top + GAP) } : { top: rect.bottom + GAP },
|
|
3951
|
+
left: align === "left" ? rect.left : Math.max(MARGIN, rect.right - PANEL_MIN_WIDTH),
|
|
3952
|
+
zIndex: 9999,
|
|
3953
|
+
minWidth: Math.max(rect.width, PANEL_MIN_WIDTH)
|
|
3954
|
+
});
|
|
3955
|
+
};
|
|
3956
|
+
reposition();
|
|
3957
|
+
const raf = window.requestAnimationFrame(reposition);
|
|
3958
|
+
window.addEventListener("scroll", reposition, true);
|
|
3959
|
+
window.addEventListener("resize", reposition);
|
|
3960
|
+
return () => {
|
|
3961
|
+
window.cancelAnimationFrame(raf);
|
|
3962
|
+
window.removeEventListener("scroll", reposition, true);
|
|
3963
|
+
window.removeEventListener("resize", reposition);
|
|
3964
|
+
};
|
|
3965
|
+
}, [
|
|
3966
|
+
open,
|
|
3967
|
+
align,
|
|
3968
|
+
items.length
|
|
3969
|
+
]);
|
|
3946
3970
|
useEffect(() => {
|
|
3947
3971
|
if (!open) return;
|
|
3948
3972
|
const handlePointerDown = (e) => {
|
|
@@ -4594,6 +4618,107 @@ function StatusPage({ eyebrow, title, description, code, icon, primaryAction, se
|
|
|
4594
4618
|
});
|
|
4595
4619
|
}
|
|
4596
4620
|
//#endregion
|
|
4621
|
+
//#region src/ui-library/gallery/not-found-error/NotFoundError.tsx
|
|
4622
|
+
/**
|
|
4623
|
+
* NotFoundError — Design System Component
|
|
4624
|
+
*
|
|
4625
|
+
* Full-page 404 Not Found screen. Composes StatusPage internally using the
|
|
4626
|
+
* `notFound` preset. Navigation is the consumer's responsibility — wire it
|
|
4627
|
+
* via `primaryAction.onClick` and `secondaryAction.onClick`.
|
|
4628
|
+
*
|
|
4629
|
+
* No routing imports. Works with any router (React Router, Next.js, window.location).
|
|
4630
|
+
*
|
|
4631
|
+
* Usage:
|
|
4632
|
+
* import { NotFoundError } from '@diwauhris/ui';
|
|
4633
|
+
* import { useNavigate } from 'react-router-dom';
|
|
4634
|
+
*
|
|
4635
|
+
* function NotFoundPage() {
|
|
4636
|
+
* const navigate = useNavigate();
|
|
4637
|
+
* return (
|
|
4638
|
+
* <NotFoundError
|
|
4639
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
4640
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
4641
|
+
* />
|
|
4642
|
+
* );
|
|
4643
|
+
* }
|
|
4644
|
+
*/
|
|
4645
|
+
function NotFoundError({ primaryAction, secondaryAction, className }) {
|
|
4646
|
+
return /* @__PURE__ */ jsx(StatusPage, {
|
|
4647
|
+
...STATUS_PAGE_PRESETS.notFound,
|
|
4648
|
+
primaryAction,
|
|
4649
|
+
secondaryAction,
|
|
4650
|
+
className
|
|
4651
|
+
});
|
|
4652
|
+
}
|
|
4653
|
+
//#endregion
|
|
4654
|
+
//#region src/ui-library/gallery/forbidden-error/ForbiddenError.tsx
|
|
4655
|
+
/**
|
|
4656
|
+
* ForbiddenError — Design System Component
|
|
4657
|
+
*
|
|
4658
|
+
* Full-page 403 Access Restricted screen. Composes StatusPage internally
|
|
4659
|
+
* using the `forbidden` preset. Navigation is the consumer's responsibility
|
|
4660
|
+
* — wire it via `primaryAction.onClick` and `secondaryAction.onClick`.
|
|
4661
|
+
*
|
|
4662
|
+
* No routing imports. Works with any router (React Router, Next.js, window.location).
|
|
4663
|
+
*
|
|
4664
|
+
* Usage:
|
|
4665
|
+
* import { ForbiddenError } from '@diwauhris/ui';
|
|
4666
|
+
* import { useNavigate } from 'react-router-dom';
|
|
4667
|
+
*
|
|
4668
|
+
* function ForbiddenPage() {
|
|
4669
|
+
* const navigate = useNavigate();
|
|
4670
|
+
* return (
|
|
4671
|
+
* <ForbiddenError
|
|
4672
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
4673
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
4674
|
+
* />
|
|
4675
|
+
* );
|
|
4676
|
+
* }
|
|
4677
|
+
*/
|
|
4678
|
+
function ForbiddenError({ primaryAction, secondaryAction, className }) {
|
|
4679
|
+
return /* @__PURE__ */ jsx(StatusPage, {
|
|
4680
|
+
...STATUS_PAGE_PRESETS.forbidden,
|
|
4681
|
+
primaryAction,
|
|
4682
|
+
secondaryAction,
|
|
4683
|
+
className
|
|
4684
|
+
});
|
|
4685
|
+
}
|
|
4686
|
+
//#endregion
|
|
4687
|
+
//#region src/ui-library/gallery/application-error/ApplicationError.tsx
|
|
4688
|
+
function ApplicationError({ error, componentStack, errorId, onRetry, onDashboard, className }) {
|
|
4689
|
+
const showDevDetails = false;
|
|
4690
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4691
|
+
className,
|
|
4692
|
+
children: [/* @__PURE__ */ jsx(StatusPage, {
|
|
4693
|
+
...STATUS_PAGE_PRESETS.serverError,
|
|
4694
|
+
primaryAction: {
|
|
4695
|
+
label: "Try Again",
|
|
4696
|
+
onClick: onRetry
|
|
4697
|
+
},
|
|
4698
|
+
secondaryAction: {
|
|
4699
|
+
label: "Go to Dashboard",
|
|
4700
|
+
onClick: onDashboard
|
|
4701
|
+
}
|
|
4702
|
+
}), showDevDetails]
|
|
4703
|
+
});
|
|
4704
|
+
}
|
|
4705
|
+
/**
|
|
4706
|
+
* Convenience wrapper for use with class-based ErrorBoundary components.
|
|
4707
|
+
* Outside router context — uses window.location.href for dashboard navigation.
|
|
4708
|
+
* Maps `onReset` to ApplicationError's `onRetry`.
|
|
4709
|
+
*/
|
|
4710
|
+
function ApplicationErrorFallback({ error, componentStack, errorId, onReset }) {
|
|
4711
|
+
return /* @__PURE__ */ jsx(ApplicationError, {
|
|
4712
|
+
error,
|
|
4713
|
+
componentStack,
|
|
4714
|
+
errorId,
|
|
4715
|
+
onRetry: onReset,
|
|
4716
|
+
onDashboard: () => {
|
|
4717
|
+
window.location.href = "/dashboard";
|
|
4718
|
+
}
|
|
4719
|
+
});
|
|
4720
|
+
}
|
|
4721
|
+
//#endregion
|
|
4597
4722
|
//#region src/ui-library/gallery/employee-card/EmployeeCard.tsx
|
|
4598
4723
|
function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className = "" }) {
|
|
4599
4724
|
return /* @__PURE__ */ jsxs("article", {
|
|
@@ -8578,4 +8703,4 @@ var shadow = {
|
|
|
8578
8703
|
overlay: "shadow-xl"
|
|
8579
8704
|
};
|
|
8580
8705
|
//#endregion
|
|
8581
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityFeed, Alert, ApprovalTimeline, AreaChart, Avatar, Badge, BarChart, BarList, Breadcrumb, Button, CHART_PALETTE, Calendar, Card, CardContent, CardFooter, CardHeader, Checkbox, ColumnManager, Combobox, CommandPalette, ConfirmAction, ConfirmDialog, DatePicker, DescriptionItem, DescriptionList, Dialog, DialogBody, DialogFooter, Divider, Drawer, Dropdown, EmployeeCard, EmptyState, ErrorBanner, Field, FieldContext, FieldInput, FileUpload, FilterChip, Heatmap, IconButton, Input, IsoCubeBlock, Kanban, LineChart, MaskedValue, Menu, Modal, OrgChart, OrgUnitTree, OtpInput, PafTemplate, PageHeader, Pagination, PayslipTemplate, PermissionMatrix, Popover, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioItem, ReportTemplate, STATUS_PAGE_PRESETS, Search, Section, SegmentedControl, Select, SidebarGroup, SidebarItem, SidebarNav, SidebarSection, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTableRow, SkeletonText, Spinner, Statistic, StatusBadge, StatusDot, StatusPage, Stepper, Switch, Tab, TabList, TabPanel, TabPanels, Tabs, Textarea, TimekeepingTemplate, Timeline, TimelineEmptyState, TimelineFooter, TimelineItem, TimelineValueCard, Toaster, Toolbar, Tooltip, TreeView, ValidationSummary, applyColumnOrder, colors_exports as colors, dimension_exports as dimension, radius_exports as radius, shadow_exports as shadow, statusMenuItems, toast, typography_exports as typography, useFieldContext };
|
|
8706
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityFeed, Alert, ApplicationError, ApplicationErrorFallback, ApprovalTimeline, AreaChart, Avatar, Badge, BarChart, BarList, Breadcrumb, Button, CHART_PALETTE, Calendar, Card, CardContent, CardFooter, CardHeader, Checkbox, ColumnManager, Combobox, CommandPalette, ConfirmAction, ConfirmDialog, DatePicker, DescriptionItem, DescriptionList, Dialog, DialogBody, DialogFooter, Divider, Drawer, Dropdown, EmployeeCard, EmptyState, ErrorBanner, Field, FieldContext, FieldInput, FileUpload, FilterChip, ForbiddenError, Heatmap, IconButton, Input, IsoCubeBlock, Kanban, LineChart, MaskedValue, Menu, Modal, NotFoundError, OrgChart, OrgUnitTree, OtpInput, PafTemplate, PageHeader, Pagination, PayslipTemplate, PermissionMatrix, Popover, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioItem, ReportTemplate, STATUS_PAGE_PRESETS, Search, Section, SegmentedControl, Select, SidebarGroup, SidebarItem, SidebarNav, SidebarSection, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTableRow, SkeletonText, Spinner, Statistic, StatusBadge, StatusDot, StatusPage, Stepper, Switch, Tab, TabList, TabPanel, TabPanels, Tabs, Textarea, TimekeepingTemplate, Timeline, TimelineEmptyState, TimelineFooter, TimelineItem, TimelineValueCard, Toaster, Toolbar, Tooltip, TreeView, ValidationSummary, applyColumnOrder, colors_exports as colors, dimension_exports as dimension, radius_exports as radius, shadow_exports as shadow, statusMenuItems, toast, typography_exports as typography, useFieldContext };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApplicationError — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* Full-page 500 / unexpected error screen. Composes StatusPage internally
|
|
5
|
+
* using the `serverError` preset. Includes a dev-only collapsible details
|
|
6
|
+
* panel (error message, stack trace, component stack) rendered only when
|
|
7
|
+
* `import.meta.env.DEV && error !== undefined`.
|
|
8
|
+
*
|
|
9
|
+
* Navigation is the consumer's responsibility — wire onRetry and onDashboard.
|
|
10
|
+
*
|
|
11
|
+
* Two exports:
|
|
12
|
+
*
|
|
13
|
+
* ApplicationError — primary component. Consumer provides both callbacks.
|
|
14
|
+
* Used as React Router `errorElement` (pair with useRouteError + useNavigate).
|
|
15
|
+
*
|
|
16
|
+
* ApplicationErrorFallback — convenience wrapper for ErrorBoundary usage.
|
|
17
|
+
* Accepts onReset (maps to onRetry) and uses window.location.href for
|
|
18
|
+
* dashboard navigation when outside router context.
|
|
19
|
+
*
|
|
20
|
+
* No routing imports in this file. Works with any router.
|
|
21
|
+
*
|
|
22
|
+
* Usage (router errorElement):
|
|
23
|
+
* import { ApplicationError } from '@diwauhris/ui';
|
|
24
|
+
* import { useRouteError, useNavigate } from 'react-router-dom';
|
|
25
|
+
*
|
|
26
|
+
* export function ErrorPage() {
|
|
27
|
+
* const error = useRouteError();
|
|
28
|
+
* const navigate = useNavigate();
|
|
29
|
+
* return (
|
|
30
|
+
* <ApplicationError
|
|
31
|
+
* error={error}
|
|
32
|
+
* onRetry={() => navigate(0)}
|
|
33
|
+
* onDashboard={() => navigate('/dashboard')}
|
|
34
|
+
* />
|
|
35
|
+
* );
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* Usage (ErrorBoundary fallback):
|
|
39
|
+
* import { ApplicationErrorFallback } from '@diwauhris/ui';
|
|
40
|
+
*
|
|
41
|
+
* <ErrorBoundary fallbackRender={({ error, resetErrorBoundary }) => (
|
|
42
|
+
* <ApplicationErrorFallback
|
|
43
|
+
* error={error}
|
|
44
|
+
* onReset={resetErrorBoundary}
|
|
45
|
+
* />
|
|
46
|
+
* )} />
|
|
47
|
+
*/
|
|
48
|
+
export interface ApplicationErrorProps {
|
|
49
|
+
/**
|
|
50
|
+
* The caught error object.
|
|
51
|
+
* Used to extract message and stack in the dev-only details panel.
|
|
52
|
+
* Pass the value from useRouteError() or ErrorBoundary's error prop.
|
|
53
|
+
*/
|
|
54
|
+
error?: unknown;
|
|
55
|
+
/**
|
|
56
|
+
* React component stack from ErrorInfo.componentStack.
|
|
57
|
+
* Shown in the dev panel when provided. Optional.
|
|
58
|
+
*/
|
|
59
|
+
componentStack?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Short error ID for support correlation (e.g. "ERR-A1B2C").
|
|
62
|
+
* Rendered below the action buttons when provided.
|
|
63
|
+
*/
|
|
64
|
+
errorId?: string;
|
|
65
|
+
/**
|
|
66
|
+
* "Try Again" callback.
|
|
67
|
+
* Router usage: () => navigate(0)
|
|
68
|
+
* Boundary usage: onReset / resetErrorBoundary
|
|
69
|
+
*/
|
|
70
|
+
onRetry: () => void;
|
|
71
|
+
/**
|
|
72
|
+
* "Go to Dashboard" callback.
|
|
73
|
+
* Router usage: () => navigate('/dashboard')
|
|
74
|
+
* Boundary usage: () => { window.location.href = '/dashboard'; }
|
|
75
|
+
*/
|
|
76
|
+
onDashboard: () => void;
|
|
77
|
+
/** Additional class on the root wrapper. */
|
|
78
|
+
className?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface ApplicationErrorFallbackProps {
|
|
81
|
+
/** The caught error object passed by the ErrorBoundary. */
|
|
82
|
+
error?: unknown;
|
|
83
|
+
/** React component stack from ErrorInfo.componentStack. */
|
|
84
|
+
componentStack?: string;
|
|
85
|
+
/** Short error ID for support correlation. */
|
|
86
|
+
errorId?: string;
|
|
87
|
+
/** Called when the user clicks "Try Again". Maps to onRetry. */
|
|
88
|
+
onReset: () => void;
|
|
89
|
+
}
|
|
90
|
+
export declare function ApplicationError({ error, componentStack, errorId, onRetry, onDashboard, className, }: ApplicationErrorProps): import("react").JSX.Element;
|
|
91
|
+
/**
|
|
92
|
+
* Convenience wrapper for use with class-based ErrorBoundary components.
|
|
93
|
+
* Outside router context — uses window.location.href for dashboard navigation.
|
|
94
|
+
* Maps `onReset` to ApplicationError's `onRetry`.
|
|
95
|
+
*/
|
|
96
|
+
export declare function ApplicationErrorFallback({ error, componentStack, errorId, onReset, }: ApplicationErrorFallbackProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForbiddenError — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* Full-page 403 Access Restricted screen. Composes StatusPage internally
|
|
5
|
+
* using the `forbidden` preset. Navigation is the consumer's responsibility
|
|
6
|
+
* — wire it via `primaryAction.onClick` and `secondaryAction.onClick`.
|
|
7
|
+
*
|
|
8
|
+
* No routing imports. Works with any router (React Router, Next.js, window.location).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* import { ForbiddenError } from '@diwauhris/ui';
|
|
12
|
+
* import { useNavigate } from 'react-router-dom';
|
|
13
|
+
*
|
|
14
|
+
* function ForbiddenPage() {
|
|
15
|
+
* const navigate = useNavigate();
|
|
16
|
+
* return (
|
|
17
|
+
* <ForbiddenError
|
|
18
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
19
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
20
|
+
* />
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
import type { StatusPageAction } from '../status-page/StatusPage';
|
|
25
|
+
export interface ForbiddenErrorProps {
|
|
26
|
+
/**
|
|
27
|
+
* Primary action button.
|
|
28
|
+
* Typically "Go to Dashboard" with onClick: () => navigate('/dashboard').
|
|
29
|
+
*/
|
|
30
|
+
primaryAction: StatusPageAction;
|
|
31
|
+
/**
|
|
32
|
+
* Optional secondary action button.
|
|
33
|
+
* Typically "Go Back" with onClick: () => navigate(-1).
|
|
34
|
+
*/
|
|
35
|
+
secondaryAction?: StatusPageAction;
|
|
36
|
+
/** Additional class on the root wrapper. */
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function ForbiddenError({ primaryAction, secondaryAction, className, }: ForbiddenErrorProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NotFoundError — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* Full-page 404 Not Found screen. Composes StatusPage internally using the
|
|
5
|
+
* `notFound` preset. Navigation is the consumer's responsibility — wire it
|
|
6
|
+
* via `primaryAction.onClick` and `secondaryAction.onClick`.
|
|
7
|
+
*
|
|
8
|
+
* No routing imports. Works with any router (React Router, Next.js, window.location).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* import { NotFoundError } from '@diwauhris/ui';
|
|
12
|
+
* import { useNavigate } from 'react-router-dom';
|
|
13
|
+
*
|
|
14
|
+
* function NotFoundPage() {
|
|
15
|
+
* const navigate = useNavigate();
|
|
16
|
+
* return (
|
|
17
|
+
* <NotFoundError
|
|
18
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
19
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
20
|
+
* />
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
import type { StatusPageAction } from '../status-page/StatusPage';
|
|
25
|
+
export interface NotFoundErrorProps {
|
|
26
|
+
/**
|
|
27
|
+
* Primary action button.
|
|
28
|
+
* Typically "Go to Dashboard" with onClick: () => navigate('/dashboard').
|
|
29
|
+
*/
|
|
30
|
+
primaryAction: StatusPageAction;
|
|
31
|
+
/**
|
|
32
|
+
* Optional secondary action button.
|
|
33
|
+
* Typically "Go Back" with onClick: () => navigate(-1).
|
|
34
|
+
*/
|
|
35
|
+
secondaryAction?: StatusPageAction;
|
|
36
|
+
/** Additional class on the root wrapper. */
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function NotFoundError({ primaryAction, secondaryAction, className, }: NotFoundErrorProps): import("react").JSX.Element;
|
|
@@ -110,6 +110,12 @@ export { EmptyState } from './gallery/empty-state/EmptyState';
|
|
|
110
110
|
export type { EmptyStateProps } from './gallery/empty-state/EmptyState';
|
|
111
111
|
export { StatusPage, STATUS_PAGE_PRESETS } from './gallery/status-page/StatusPage';
|
|
112
112
|
export type { StatusPageProps, StatusPageAction } from './gallery/status-page/StatusPage';
|
|
113
|
+
export { NotFoundError } from './gallery/not-found-error/NotFoundError';
|
|
114
|
+
export type { NotFoundErrorProps } from './gallery/not-found-error/NotFoundError';
|
|
115
|
+
export { ForbiddenError } from './gallery/forbidden-error/ForbiddenError';
|
|
116
|
+
export type { ForbiddenErrorProps } from './gallery/forbidden-error/ForbiddenError';
|
|
117
|
+
export { ApplicationError, ApplicationErrorFallback } from './gallery/application-error/ApplicationError';
|
|
118
|
+
export type { ApplicationErrorProps, ApplicationErrorFallbackProps } from './gallery/application-error/ApplicationError';
|
|
113
119
|
export { EmployeeCard } from './gallery/employee-card/EmployeeCard';
|
|
114
120
|
export type { EmployeeCardProps, EmployeeCardMeta } from './gallery/employee-card/EmployeeCard';
|
|
115
121
|
export { TreeView } from './gallery/tree-view/TreeView';
|