@diwauhris/ui 1.5.0 → 1.7.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/lib/assets/ui.css +134 -51
- package/lib/index.cjs +2847 -115
- package/lib/index.mjs +2836 -118
- package/lib/types/ui-library/gallery/charts/AreaChart.d.ts +110 -0
- package/lib/types/ui-library/gallery/charts/BarList.d.ts +65 -0
- package/lib/types/ui-library/gallery/charts/Charts.d.ts +21 -5
- package/lib/types/ui-library/gallery/combobox/Combobox.d.ts +2 -1
- package/lib/types/ui-library/gallery/org-chart/OrgChart.d.ts +77 -0
- package/lib/types/ui-library/gallery/org-unit-tree/OrgUnitTree.d.ts +84 -0
- package/lib/types/ui-library/gallery/page-sample/IsoCubeBlock.d.ts +28 -0
- package/lib/types/ui-library/gallery/status-page/StatusPage.d.ts +112 -0
- package/lib/types/ui-library/gallery/template-samples/templates/PafTemplate.d.ts +57 -0
- package/lib/types/ui-library/gallery/template-samples/templates/PayslipTemplate.d.ts +42 -0
- package/lib/types/ui-library/gallery/template-samples/templates/ReportTemplate.d.ts +18 -0
- package/lib/types/ui-library/gallery/template-samples/templates/TimekeepingTemplate.d.ts +22 -0
- package/lib/types/ui-library/index.d.ts +21 -1
- package/lib/types/ui-library/registry.d.ts +3 -9
- package/package.json +15 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AreaChart — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* SVG area/line chart with gradient fill, explicit Y-axis ticks, optional
|
|
5
|
+
* threshold line, point annotations, highlight regions, and multi-series support.
|
|
6
|
+
* No external charting library — native SVG only.
|
|
7
|
+
*
|
|
8
|
+
* Gradient IDs are scoped per instance via useId() to avoid SVG ID collisions
|
|
9
|
+
* when multiple charts appear on the same page.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <AreaChart
|
|
13
|
+
* data={monthlyData}
|
|
14
|
+
* series={{ dataKey: 'value', color: '#6366f1', fillOpacity: { top: 0.22, bottom: 0.01 } }}
|
|
15
|
+
* yTicks={[0, 25, 50, 75, 100]}
|
|
16
|
+
* yTickFormat={(v) => `${v}%`}
|
|
17
|
+
* annotations={[{ dataIndex: 5, label: 'Peak', radius: 5, color: '#ef4444' }]}
|
|
18
|
+
* height={170}
|
|
19
|
+
* />
|
|
20
|
+
*
|
|
21
|
+
* Accessibility:
|
|
22
|
+
* - role="img" on the SVG with aria-label
|
|
23
|
+
* - Each dot has aria-label with label and value
|
|
24
|
+
* - Decorative elements are aria-hidden
|
|
25
|
+
*/
|
|
26
|
+
/** Independent top/bottom gradient stop opacities */
|
|
27
|
+
export interface GradientOpacity {
|
|
28
|
+
top: number;
|
|
29
|
+
bottom: number;
|
|
30
|
+
}
|
|
31
|
+
export interface AreaChartSeries {
|
|
32
|
+
/** Key in each data point object that holds the Y value */
|
|
33
|
+
dataKey: string;
|
|
34
|
+
/** Stroke and fill color (hex or rgb) */
|
|
35
|
+
color: string;
|
|
36
|
+
/** Stroke style. Default: 'solid' */
|
|
37
|
+
strokeStyle?: 'solid' | 'dashed';
|
|
38
|
+
/**
|
|
39
|
+
* Gradient area fill opacity.
|
|
40
|
+
* - number: same value applied to both top and bottom gradient stops
|
|
41
|
+
* - { top, bottom }: independent stop opacities for precise gradient control
|
|
42
|
+
* Default: { top: 0.15, bottom: 0 }
|
|
43
|
+
*/
|
|
44
|
+
fillOpacity?: number | GradientOpacity;
|
|
45
|
+
}
|
|
46
|
+
export interface ThresholdLine {
|
|
47
|
+
/** Data value at which the horizontal reference line is drawn */
|
|
48
|
+
value: number;
|
|
49
|
+
/** Line color. Default: '#f59e0b' */
|
|
50
|
+
color?: string;
|
|
51
|
+
/** Line style. Default: 'dashed' */
|
|
52
|
+
strokeStyle?: 'solid' | 'dashed';
|
|
53
|
+
}
|
|
54
|
+
export interface ChartAnnotation {
|
|
55
|
+
/** Zero-based index into the data array */
|
|
56
|
+
dataIndex: number;
|
|
57
|
+
/** Text label rendered near the dot */
|
|
58
|
+
label: string;
|
|
59
|
+
/** Dot radius in SVG units. Default: 4 */
|
|
60
|
+
radius?: number;
|
|
61
|
+
/** Dot and label color. Defaults to the primary series color */
|
|
62
|
+
color?: string;
|
|
63
|
+
/** Position of the label relative to the dot. Default: 'above' */
|
|
64
|
+
labelPosition?: 'above' | 'below';
|
|
65
|
+
}
|
|
66
|
+
export interface HighlightRegion {
|
|
67
|
+
/** Inclusive start index */
|
|
68
|
+
startIndex: number;
|
|
69
|
+
/** Inclusive end index */
|
|
70
|
+
endIndex: number;
|
|
71
|
+
/** Fill color for the shaded region. Default: '#eef0ff' */
|
|
72
|
+
color?: string;
|
|
73
|
+
/** Optional label centered over the region */
|
|
74
|
+
label?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface AreaChartDataPoint {
|
|
77
|
+
/** X-axis label */
|
|
78
|
+
label: string;
|
|
79
|
+
[key: string]: string | number;
|
|
80
|
+
}
|
|
81
|
+
export interface AreaChartProps {
|
|
82
|
+
/** Data points — each must have a 'label' string plus the series dataKey(s) */
|
|
83
|
+
data: AreaChartDataPoint[];
|
|
84
|
+
/**
|
|
85
|
+
* Series definition(s). Pass a single object for one series or an array for
|
|
86
|
+
* multi-series. Only the first series receives the gradient area fill.
|
|
87
|
+
*/
|
|
88
|
+
series: AreaChartSeries | AreaChartSeries[];
|
|
89
|
+
/** Explicit Y-axis tick values. When omitted, no Y-axis grid lines are drawn. */
|
|
90
|
+
yTicks?: number[];
|
|
91
|
+
/** Format Y-axis tick labels. Default: String(v) */
|
|
92
|
+
yTickFormat?: (value: number) => string;
|
|
93
|
+
/**
|
|
94
|
+
* Show data-point circles on the primary series line.
|
|
95
|
+
* Default: true — pass false for charts where dots are not desired.
|
|
96
|
+
*/
|
|
97
|
+
showDots?: boolean;
|
|
98
|
+
/** Horizontal threshold reference line */
|
|
99
|
+
threshold?: ThresholdLine;
|
|
100
|
+
/** Annotated data points rendered on top of regular dots */
|
|
101
|
+
annotations?: ChartAnnotation[];
|
|
102
|
+
/** Shaded background region between two x-axis indices */
|
|
103
|
+
highlightRegion?: HighlightRegion;
|
|
104
|
+
/** SVG height in pixels. Default: 170 */
|
|
105
|
+
height?: number;
|
|
106
|
+
/** Accessible description for screen readers */
|
|
107
|
+
'aria-label'?: string;
|
|
108
|
+
className?: string;
|
|
109
|
+
}
|
|
110
|
+
export declare function AreaChart({ data, series, yTicks, yTickFormat, showDots, threshold, annotations, highlightRegion, height, 'aria-label': ariaLabel, className, }: AreaChartProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BarList — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* Ranked horizontal bar list for categorical value distributions.
|
|
5
|
+
* Bars animate in from the left via .os-bar-in with configurable stagger.
|
|
6
|
+
* No external library — pure CSS animation.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* <BarList
|
|
10
|
+
* items={[
|
|
11
|
+
* { label: 'Category A', value: 94, color: '#3b82f6' },
|
|
12
|
+
* { label: 'Category B', value: 72, color: '#6366f1' },
|
|
13
|
+
* ]}
|
|
14
|
+
* totalLabel="Total"
|
|
15
|
+
* staggerDelay={70}
|
|
16
|
+
* />
|
|
17
|
+
*
|
|
18
|
+
* Accessibility:
|
|
19
|
+
* - role="list" / role="listitem" semantics
|
|
20
|
+
* - aria-label on each row conveys label + formatted value
|
|
21
|
+
* - Bar fill is aria-hidden (data already conveyed by listitem label)
|
|
22
|
+
* - .os-bar-in respects prefers-reduced-motion
|
|
23
|
+
*/
|
|
24
|
+
export interface BarListItem {
|
|
25
|
+
/** Row label */
|
|
26
|
+
label: string;
|
|
27
|
+
/** Raw numeric value */
|
|
28
|
+
value: number;
|
|
29
|
+
/**
|
|
30
|
+
* CSS color for the bar fill — hex, rgb, or named color only.
|
|
31
|
+
* Do NOT pass Tailwind class names (e.g. 'bg-blue-500') — they will
|
|
32
|
+
* not resolve at runtime and the bar will render colorless.
|
|
33
|
+
*/
|
|
34
|
+
color: string;
|
|
35
|
+
}
|
|
36
|
+
export type BarHeight = 'h-1' | 'h-2' | 'h-2.5' | 'h-3' | 'h-4';
|
|
37
|
+
export interface BarListProps {
|
|
38
|
+
/** Data rows */
|
|
39
|
+
items: BarListItem[];
|
|
40
|
+
/**
|
|
41
|
+
* Format the displayed value string.
|
|
42
|
+
* Default: bare number.
|
|
43
|
+
* Example: (v) => `${v}%` or (v) => `${v} users`
|
|
44
|
+
*/
|
|
45
|
+
valueFormat?: (value: number) => string;
|
|
46
|
+
/**
|
|
47
|
+
* Label for the total row shown at the bottom of the list.
|
|
48
|
+
* When omitted, no total row is rendered.
|
|
49
|
+
*/
|
|
50
|
+
totalLabel?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Tailwind height class applied to both the bar track and the fill.
|
|
53
|
+
* Default: 'h-2'
|
|
54
|
+
*/
|
|
55
|
+
barHeight?: BarHeight;
|
|
56
|
+
/**
|
|
57
|
+
* Stagger delay between bar animations in milliseconds.
|
|
58
|
+
* Each bar at index i receives: animationDelay = i × staggerDelay ms.
|
|
59
|
+
* Pass 0 to animate all bars simultaneously.
|
|
60
|
+
* Default: 70
|
|
61
|
+
*/
|
|
62
|
+
staggerDelay?: number;
|
|
63
|
+
className?: string;
|
|
64
|
+
}
|
|
65
|
+
export declare function BarList({ items, valueFormat, totalLabel, barHeight, staggerDelay, className, }: BarListProps): import("react").JSX.Element;
|
|
@@ -5,14 +5,30 @@
|
|
|
5
5
|
* Suitable for simple analytics/KPI displays.
|
|
6
6
|
*
|
|
7
7
|
* Components:
|
|
8
|
-
* BarChart
|
|
9
|
-
* LineChart
|
|
8
|
+
* BarChart — vertical bar chart
|
|
9
|
+
* LineChart — line/area chart (SVG path)
|
|
10
|
+
* CHART_PALETTE — shared default color sequence for multi-series charts
|
|
11
|
+
*
|
|
12
|
+
* Visual language (applied as defaults, no new props):
|
|
13
|
+
* - BarChart: top-only rounded corners, subtle same-hue gradient fill,
|
|
14
|
+
* baseline rule, value labels inside SVG above bars, comfortable gaps
|
|
15
|
+
* - LineChart: gradient area fill fading to transparent, strokeWidth 2,
|
|
16
|
+
* white-ring dots only when ≤ 12 data points, no horizontal distortion
|
|
10
17
|
*
|
|
11
18
|
* Accessibility:
|
|
12
|
-
* - role="img" on
|
|
13
|
-
* - Each bar/point has aria-label with value
|
|
14
|
-
* -
|
|
19
|
+
* - role="img" on every SVG with aria-label describing the chart
|
|
20
|
+
* - Each bar/point has aria-label with label and value
|
|
21
|
+
* - Decorative elements are aria-hidden
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Default color sequence for multi-series / per-item charts.
|
|
25
|
+
* Built on the brand's blue-sky hue family with a single warm accent.
|
|
26
|
+
* Import this directly when constructing per-item color arrays:
|
|
27
|
+
*
|
|
28
|
+
* import { CHART_PALETTE } from '@diwauhris/ui';
|
|
29
|
+
* const data = items.map((item, i) => ({ ...item, color: CHART_PALETTE[i % CHART_PALETTE.length] }));
|
|
15
30
|
*/
|
|
31
|
+
export declare const CHART_PALETTE: readonly ["#034EA2", "#2D8ACA", "#4F6FBF", "#0E7490", "#B45309"];
|
|
16
32
|
export interface ChartDataPoint {
|
|
17
33
|
label: string;
|
|
18
34
|
value: number;
|
|
@@ -10,5 +10,6 @@ export interface ComboboxProps {
|
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
loading?: boolean;
|
|
12
12
|
error?: string;
|
|
13
|
+
'aria-label'?: string;
|
|
13
14
|
}
|
|
14
|
-
export declare function Combobox({ value, onChange, options, placeholder, className, disabled, loading, error }: ComboboxProps): import("react").JSX.Element;
|
|
15
|
+
export declare function Combobox({ value, onChange, options, placeholder, className, disabled, loading, error, 'aria-label': ariaLabel }: ComboboxProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrgChart — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* A D3-powered SVG organization chart matching the UHRIS Company Structure
|
|
5
|
+
* diagram mode. Renders a top-down tree with rectangular nodes and
|
|
6
|
+
* stepped orthogonal connectors.
|
|
7
|
+
*
|
|
8
|
+
* Technology: D3 v7 (d3.hierarchy + d3.tree layout + d3.zoom)
|
|
9
|
+
* Already a production dependency — no new packages introduced.
|
|
10
|
+
*
|
|
11
|
+
* Visual design (sourced from CompanyStructurePage diagram mode):
|
|
12
|
+
* Nodes:
|
|
13
|
+
* - 250 × 84 px rounded rectangles (rx=14)
|
|
14
|
+
* - Root (depth 0): dark navy fill (#0f172a), white text
|
|
15
|
+
* - Children: white fill (#fff), slate border (#e2e8f0)
|
|
16
|
+
* - drop-shadow: 0 6px 12px rgba(15,23,42,0.08)
|
|
17
|
+
* - Name: 13px, font-weight 800, centered
|
|
18
|
+
* - Description: 11px, font-weight 600, #64748b / #cbd5e1 (root)
|
|
19
|
+
* - Selected: indigo border overlay ring
|
|
20
|
+
* Connectors:
|
|
21
|
+
* - Stepped orthogonal path: M→V→H→V
|
|
22
|
+
* - Stroke: #cbd5e1, stroke-width 1.5
|
|
23
|
+
* Canvas:
|
|
24
|
+
* - Viewport sized to container; fit-to-view on render
|
|
25
|
+
* - Zoom: scaleExtent [0.05, 1.8]
|
|
26
|
+
* - Pan: mouse/touch drag
|
|
27
|
+
* - Layout: nodeSize [280, 185] — horizontal × vertical spacing
|
|
28
|
+
* Controls:
|
|
29
|
+
* - ZoomIn, Reset, ZoomOut buttons (top-right overlay panel)
|
|
30
|
+
*
|
|
31
|
+
* Accessibility:
|
|
32
|
+
* - SVG has role="img" + aria-label
|
|
33
|
+
* - Zoom controls have aria-label
|
|
34
|
+
* - Keyboard: Tab to control buttons; diagram itself is navigated visually
|
|
35
|
+
* - Note: full ARIA tree semantics are not possible in an SVG diagram;
|
|
36
|
+
* use OrgUnitTree for a fully keyboard-accessible list-based alternative
|
|
37
|
+
*
|
|
38
|
+
* Usage:
|
|
39
|
+
* <OrgChart
|
|
40
|
+
* nodes={orgNodes}
|
|
41
|
+
* selectedId={selectedId}
|
|
42
|
+
* onSelect={setSelectedId}
|
|
43
|
+
* aria-label="Company organization chart"
|
|
44
|
+
* />
|
|
45
|
+
*/
|
|
46
|
+
export interface OrgChartNode {
|
|
47
|
+
/** Unique identifier. */
|
|
48
|
+
id: string;
|
|
49
|
+
/** Primary label — org unit name. */
|
|
50
|
+
label: string;
|
|
51
|
+
/** Secondary text line inside the node. */
|
|
52
|
+
description?: string;
|
|
53
|
+
/** Child nodes. */
|
|
54
|
+
children?: OrgChartNode[];
|
|
55
|
+
}
|
|
56
|
+
export interface OrgChartProps {
|
|
57
|
+
/**
|
|
58
|
+
* Root-level nodes. The chart renders one connected tree.
|
|
59
|
+
* If multiple roots are provided, a synthetic invisible root is created
|
|
60
|
+
* to connect them (matching D3 hierarchy requirements).
|
|
61
|
+
*/
|
|
62
|
+
nodes: OrgChartNode[];
|
|
63
|
+
/** Currently selected node id — renders an indigo ring on the node. */
|
|
64
|
+
selectedId?: string;
|
|
65
|
+
/** Called when a node is clicked. */
|
|
66
|
+
onSelect?: (id: string) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Container height. Default: '75vh' — matching the production CompanyStructurePage.
|
|
69
|
+
* Pass a fixed pixel value for demos: '480px'.
|
|
70
|
+
*/
|
|
71
|
+
height?: string;
|
|
72
|
+
/** Accessible label for the SVG element. */
|
|
73
|
+
'aria-label'?: string;
|
|
74
|
+
/** Additional class on the root container div. */
|
|
75
|
+
className?: string;
|
|
76
|
+
}
|
|
77
|
+
export declare function OrgChart({ nodes, selectedId, onSelect, height, 'aria-label': ariaLabel, className, }: OrgChartProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrgUnitTree — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* A card-based hierarchical organization tree matching the UHRIS
|
|
5
|
+
* Company Structure list-mode visual design. Purely presentational —
|
|
6
|
+
* no API calls, no domain logic, no permissions.
|
|
7
|
+
*
|
|
8
|
+
* Visual design (sourced from CompanyStructurePage StructureDesigner):
|
|
9
|
+
* - Root node: dark navy (bg-slate-900) card with light text
|
|
10
|
+
* - Child nodes: white bordered cards with blue hover accent
|
|
11
|
+
* - Connector: left border (border-l border-slate-200) + indentation
|
|
12
|
+
* - Icon badge: rounded-xl colored square containing the icon
|
|
13
|
+
* - Actions: hover-reveal slot (opacity-0 → group-hover:opacity-100)
|
|
14
|
+
* - Meta: right-aligned, hidden on narrow screens
|
|
15
|
+
*
|
|
16
|
+
* Accessibility (WAI-ARIA Tree pattern, RFC 1.2):
|
|
17
|
+
* - role="tree" on root list
|
|
18
|
+
* - role="treeitem" + aria-expanded + aria-selected + aria-level + aria-disabled
|
|
19
|
+
* - role="group" on nested lists
|
|
20
|
+
* - Keyboard: ArrowDown/Up/Left/Right/Home/End/Enter/Space
|
|
21
|
+
* - Roving tabIndex: only focused item has tabIndex=0
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* <OrgUnitTree
|
|
25
|
+
* nodes={orgNodes}
|
|
26
|
+
* onSelect={(id) => navigate(`/org/${id}`)}
|
|
27
|
+
* aria-label="Company structure"
|
|
28
|
+
* />
|
|
29
|
+
*/
|
|
30
|
+
import { type ReactNode } from 'react';
|
|
31
|
+
export interface OrgUnitNode {
|
|
32
|
+
/** Unique identifier. */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Primary label (org unit name). */
|
|
35
|
+
label: string;
|
|
36
|
+
/** Secondary label shown below the main label. */
|
|
37
|
+
description?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Icon rendered inside the colored badge square.
|
|
40
|
+
* Mark it aria-hidden="true" — the label is the accessible name.
|
|
41
|
+
*/
|
|
42
|
+
icon?: ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* Right-side metadata slot (headcount, budget, status counts…).
|
|
45
|
+
* Caller provides any ReactNode. Hidden below md breakpoint.
|
|
46
|
+
*/
|
|
47
|
+
meta?: ReactNode;
|
|
48
|
+
/**
|
|
49
|
+
* Action buttons shown on hover/focus-within.
|
|
50
|
+
* Use <IconButton aria-label="Edit {name}" />.
|
|
51
|
+
*/
|
|
52
|
+
actions?: ReactNode;
|
|
53
|
+
/** Inline badge (StatusBadge, "Unit Head" tag, etc.). */
|
|
54
|
+
badge?: ReactNode;
|
|
55
|
+
/** Child nodes. */
|
|
56
|
+
children?: OrgUnitNode[];
|
|
57
|
+
/** Prevents selection; node is skipped by keyboard navigation. */
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface OrgUnitTreeProps {
|
|
61
|
+
/** Root-level nodes. */
|
|
62
|
+
nodes: OrgUnitNode[];
|
|
63
|
+
/** Currently selected node id. */
|
|
64
|
+
selectedId?: string;
|
|
65
|
+
/** Called when a node is selected via click or keyboard. */
|
|
66
|
+
onSelect?: (id: string) => void;
|
|
67
|
+
/**
|
|
68
|
+
* IDs that start expanded (uncontrolled).
|
|
69
|
+
* Defaults to top-level node IDs.
|
|
70
|
+
*/
|
|
71
|
+
defaultExpandedIds?: string[];
|
|
72
|
+
/**
|
|
73
|
+
* Controlled expanded IDs. When provided, caller owns expansion state.
|
|
74
|
+
* Must supply onExpandedChange to update.
|
|
75
|
+
*/
|
|
76
|
+
expandedIds?: string[];
|
|
77
|
+
/** Called when expansion state changes (controlled mode). */
|
|
78
|
+
onExpandedChange?: (ids: string[]) => void;
|
|
79
|
+
/** Accessible label for the tree. */
|
|
80
|
+
'aria-label'?: string;
|
|
81
|
+
/** Additional class on the root element. */
|
|
82
|
+
className?: string;
|
|
83
|
+
}
|
|
84
|
+
export declare function OrgUnitTree({ nodes, selectedId, onSelect, defaultExpandedIds, expandedIds: controlledExpandedIds, onExpandedChange, 'aria-label': ariaLabel, className, }: OrgUnitTreeProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IsoCubeBlock — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* DIWA brand geometric watermark — isometric staircase boxes.
|
|
5
|
+
* Reference: DIWA Certificate bottom-right corner decoration.
|
|
6
|
+
*
|
|
7
|
+
* Three-faced isometric boxes arranged in a 4×4 diagonal staircase
|
|
8
|
+
* (bottom-left → top-right). Drop it as an absolute-positioned child
|
|
9
|
+
* in any container to get the brand watermark effect.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <div className="relative overflow-hidden">
|
|
13
|
+
* <IsoCubeBlock />
|
|
14
|
+
* {children}
|
|
15
|
+
* </div>
|
|
16
|
+
*
|
|
17
|
+
* Colors match DIWA Certificate spec:
|
|
18
|
+
* top face #F3F3F5 (light grey)
|
|
19
|
+
* left face #7D739B (brand purple)
|
|
20
|
+
* right face #9B92B8 (lighter purple)
|
|
21
|
+
*/
|
|
22
|
+
export interface IsoCubeBlockProps {
|
|
23
|
+
/** Width of each box in SVG units. Default: 80 */
|
|
24
|
+
boxWidth?: number;
|
|
25
|
+
/** Additional className on the SVG element */
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function IsoCubeBlock({ boxWidth, className }: IsoCubeBlockProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusPage — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* Full-page status screen for 404, 403, 500, and custom states.
|
|
5
|
+
*
|
|
6
|
+
* Signature element: the status code itself rendered as a large Barlow
|
|
7
|
+
* watermark behind the heading — brand typography as the primary visual,
|
|
8
|
+
* no icon-in-a-circle required.
|
|
9
|
+
*
|
|
10
|
+
* Layout: full-page centered on bg-surface-page, no card wrapper.
|
|
11
|
+
* Motion: content block enters with .os-slide-up (respects prefers-reduced-motion).
|
|
12
|
+
* Watermark stays static — animating it would be distracting.
|
|
13
|
+
*
|
|
14
|
+
* No routing logic in this component. Action buttons accept onClick/href;
|
|
15
|
+
* the consumer wires navigation (e.g. useNavigate from react-router-dom).
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* <StatusPage
|
|
19
|
+
* {...STATUS_PAGE_PRESETS.notFound}
|
|
20
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
21
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
22
|
+
* />
|
|
23
|
+
*
|
|
24
|
+
* Accessibility:
|
|
25
|
+
* - Heading is <h1> — appropriate for a full-page status screen.
|
|
26
|
+
* - Watermark is aria-hidden="true" — decorative; the heading communicates the state.
|
|
27
|
+
* - Action buttons have descriptive labels via the `label` prop.
|
|
28
|
+
* - The watermark is opacity-[0.07] and has no contrast requirement (aria-hidden).
|
|
29
|
+
*/
|
|
30
|
+
import type { ReactNode } from 'react';
|
|
31
|
+
export interface StatusPageAction {
|
|
32
|
+
/** Button label */
|
|
33
|
+
label: string;
|
|
34
|
+
/**
|
|
35
|
+
* Click handler — consumer wires navigation.
|
|
36
|
+
* Example: () => navigate('/dashboard')
|
|
37
|
+
*/
|
|
38
|
+
onClick?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Renders an <a> tag instead of <button> when provided.
|
|
41
|
+
* Use for external links (e.g. a status-page URL) or non-SPA navigation.
|
|
42
|
+
*/
|
|
43
|
+
href?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface StatusPageProps {
|
|
46
|
+
/**
|
|
47
|
+
* Short eyebrow label shown above the heading.
|
|
48
|
+
* Rendered in the brand-sky uppercase tracking style.
|
|
49
|
+
* Example: "404 — Not Found"
|
|
50
|
+
* Omit to skip the eyebrow row.
|
|
51
|
+
*/
|
|
52
|
+
eyebrow?: string;
|
|
53
|
+
/** Main heading. Rendered as <h1>. Required. */
|
|
54
|
+
title: string;
|
|
55
|
+
/** Body description below the heading. Rendered as <p>. Required. */
|
|
56
|
+
description: string;
|
|
57
|
+
/**
|
|
58
|
+
* Status code string used as the large typographic watermark
|
|
59
|
+
* rendered behind the heading (e.g. "404", "403", "500").
|
|
60
|
+
* When omitted and `icon` is provided, the icon renders as the
|
|
61
|
+
* background mark instead.
|
|
62
|
+
*/
|
|
63
|
+
code?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Lucide icon used as the background mark when `code` is not set.
|
|
66
|
+
* Ignored when `code` is provided.
|
|
67
|
+
* Pass with aria-hidden="true"; rendered at large size automatically.
|
|
68
|
+
*/
|
|
69
|
+
icon?: ReactNode;
|
|
70
|
+
/** Primary action — rendered as Button variant="primary". */
|
|
71
|
+
primaryAction?: StatusPageAction;
|
|
72
|
+
/**
|
|
73
|
+
* Secondary action — rendered as Button variant="outline".
|
|
74
|
+
* Omit for single-action states.
|
|
75
|
+
*/
|
|
76
|
+
secondaryAction?: StatusPageAction;
|
|
77
|
+
/** Additional class on the root wrapper. */
|
|
78
|
+
className?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Named presets for the three common status states.
|
|
82
|
+
* Each preset supplies code, eyebrow, title, and description.
|
|
83
|
+
* Consumer always provides actions — presets never include navigation.
|
|
84
|
+
*
|
|
85
|
+
* Usage:
|
|
86
|
+
* <StatusPage
|
|
87
|
+
* {...STATUS_PAGE_PRESETS.notFound}
|
|
88
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
89
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
90
|
+
* />
|
|
91
|
+
*/
|
|
92
|
+
export declare const STATUS_PAGE_PRESETS: {
|
|
93
|
+
readonly notFound: {
|
|
94
|
+
readonly code: "404";
|
|
95
|
+
readonly eyebrow: "404 — Not Found";
|
|
96
|
+
readonly title: "Page Not Found";
|
|
97
|
+
readonly description: "The page you're looking for doesn't exist or may have been moved.";
|
|
98
|
+
};
|
|
99
|
+
readonly forbidden: {
|
|
100
|
+
readonly code: "403";
|
|
101
|
+
readonly eyebrow: "403 — Access Restricted";
|
|
102
|
+
readonly title: "Access Restricted";
|
|
103
|
+
readonly description: "You don't have permission to view this page. Contact your system administrator if you need access.";
|
|
104
|
+
};
|
|
105
|
+
readonly serverError: {
|
|
106
|
+
readonly code: "500";
|
|
107
|
+
readonly eyebrow: "500 — Server Error";
|
|
108
|
+
readonly title: "Something Went Wrong";
|
|
109
|
+
readonly description: "We encountered an unexpected problem. Please try again or return to the dashboard.";
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
export declare function StatusPage({ eyebrow, title, description, code, icon, primaryAction, secondaryAction, className, }: StatusPageProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PafTemplate — self-contained preview component
|
|
3
|
+
*
|
|
4
|
+
* Ported from unified-hris/components/PAFTemplate.tsx.
|
|
5
|
+
* All context deps removed. Data passed via props.
|
|
6
|
+
*/
|
|
7
|
+
interface PafSalaryComponent {
|
|
8
|
+
label: string;
|
|
9
|
+
from: string;
|
|
10
|
+
to: string;
|
|
11
|
+
}
|
|
12
|
+
export interface PafPreviewData {
|
|
13
|
+
id: string;
|
|
14
|
+
type: string;
|
|
15
|
+
date: string;
|
|
16
|
+
effectiveDate?: string;
|
|
17
|
+
fromTemplate?: string;
|
|
18
|
+
toTemplate?: string;
|
|
19
|
+
employee: {
|
|
20
|
+
name: string;
|
|
21
|
+
idNo: string;
|
|
22
|
+
position: string;
|
|
23
|
+
department: string;
|
|
24
|
+
dateHired?: string;
|
|
25
|
+
};
|
|
26
|
+
from: {
|
|
27
|
+
rank: string;
|
|
28
|
+
status: string;
|
|
29
|
+
position: string;
|
|
30
|
+
department: string;
|
|
31
|
+
company: string;
|
|
32
|
+
supervisor: string;
|
|
33
|
+
departmentHead: string;
|
|
34
|
+
basicSalary: string;
|
|
35
|
+
};
|
|
36
|
+
to: {
|
|
37
|
+
rank: string;
|
|
38
|
+
status: string;
|
|
39
|
+
position: string;
|
|
40
|
+
department: string;
|
|
41
|
+
company: string;
|
|
42
|
+
supervisor: string;
|
|
43
|
+
departmentHead: string;
|
|
44
|
+
basicSalary: string;
|
|
45
|
+
};
|
|
46
|
+
reason: string;
|
|
47
|
+
preparedBy: string;
|
|
48
|
+
preparedByTitle?: string;
|
|
49
|
+
approvedBy?: string;
|
|
50
|
+
approvedByTitle?: string;
|
|
51
|
+
salaryComponents?: PafSalaryComponent[];
|
|
52
|
+
}
|
|
53
|
+
interface Props {
|
|
54
|
+
data: PafPreviewData;
|
|
55
|
+
}
|
|
56
|
+
export declare function PafTemplate({ data }: Props): import("react").JSX.Element;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayslipTemplate — self-contained preview component
|
|
3
|
+
*
|
|
4
|
+
* Ported from unified-hris/components/PayslipTemplate.tsx.
|
|
5
|
+
* No context deps. All data prop-driven with sane defaults.
|
|
6
|
+
*/
|
|
7
|
+
export interface PayslipPreviewData {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
role: string;
|
|
11
|
+
department: string;
|
|
12
|
+
payPeriod?: string;
|
|
13
|
+
netPay?: number;
|
|
14
|
+
rates?: {
|
|
15
|
+
hourly: number;
|
|
16
|
+
daily: number;
|
|
17
|
+
monthly: number;
|
|
18
|
+
};
|
|
19
|
+
taxCode?: string;
|
|
20
|
+
taxableGross?: number;
|
|
21
|
+
nonTaxableGross?: number;
|
|
22
|
+
ytd?: {
|
|
23
|
+
gross: number;
|
|
24
|
+
tax: number;
|
|
25
|
+
};
|
|
26
|
+
leaveBalances?: {
|
|
27
|
+
vacation: {
|
|
28
|
+
remaining: number;
|
|
29
|
+
};
|
|
30
|
+
sick: {
|
|
31
|
+
remaining: number;
|
|
32
|
+
};
|
|
33
|
+
personal?: {
|
|
34
|
+
remaining: number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface Props {
|
|
39
|
+
data: PayslipPreviewData;
|
|
40
|
+
}
|
|
41
|
+
export declare function PayslipTemplate({ data }: Props): import("react").JSX.Element;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReportTemplate — self-contained preview component
|
|
3
|
+
*
|
|
4
|
+
* A generic HRIS Masterlist / Report document layout.
|
|
5
|
+
* Mimics the tabular report format used in unified-hris reports.
|
|
6
|
+
*/
|
|
7
|
+
export interface ReportPreviewData {
|
|
8
|
+
title?: string;
|
|
9
|
+
subtitle?: string;
|
|
10
|
+
asOf?: string;
|
|
11
|
+
preparedBy?: string;
|
|
12
|
+
company?: string;
|
|
13
|
+
}
|
|
14
|
+
interface Props {
|
|
15
|
+
data: ReportPreviewData;
|
|
16
|
+
}
|
|
17
|
+
export declare function ReportTemplate({ data }: Props): import("react").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TimekeepingTemplate — self-contained preview component
|
|
3
|
+
*
|
|
4
|
+
* Ported from unified-hris/components/TimekeepingFileTemplate.tsx.
|
|
5
|
+
* No context deps. All data is mock + prop-driven.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface TimekeepingPreviewData {
|
|
9
|
+
employee: {
|
|
10
|
+
name: string;
|
|
11
|
+
role: string;
|
|
12
|
+
department: string;
|
|
13
|
+
empId?: string;
|
|
14
|
+
supervisor?: string;
|
|
15
|
+
};
|
|
16
|
+
period: string;
|
|
17
|
+
}
|
|
18
|
+
interface Props {
|
|
19
|
+
data: TimekeepingPreviewData;
|
|
20
|
+
}
|
|
21
|
+
export declare function TimekeepingTemplate({ data }: Props): React.JSX.Element;
|
|
22
|
+
export {};
|