@pablo2410/shared-ui 0.3.2

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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @oplytics/shared-ui/rbac
3
+ *
4
+ * Standardised Role-Based Access Control for all Oplytics.digital subdomains.
5
+ * Single source of truth for the 7-role model, permission checks, and error messages.
6
+ */
7
+ declare const COOKIE_NAME = "app_session_id";
8
+ declare const ONE_YEAR_MS: number;
9
+ declare const AXIOS_TIMEOUT_MS = 30000;
10
+ declare const UNAUTHED_ERR_MSG = "Please login (10001)";
11
+ declare const NOT_ADMIN_ERR_MSG = "You do not have required permission (10002)";
12
+ declare const NOT_PLATFORM_ADMIN_ERR_MSG = "Platform admin access required (10003)";
13
+ declare const NOT_ENTERPRISE_ADMIN_ERR_MSG = "Enterprise admin access required (10004)";
14
+ declare const NO_ENTERPRISE_ERR_MSG = "Enterprise context not resolved. Please ensure your account is linked to an enterprise in the portal. (10005)";
15
+ declare const NOT_SUPERUSER_ERR_MSG = "This action requires superuser access or above (10006)";
16
+ /**
17
+ * Services restricted to platform_admin role only.
18
+ * These services are NOT visible in ServiceHub, Portal, marketing pages, or footer.
19
+ * They can only be assigned/revoked by platform_admin users.
20
+ * Non-platform-admin users cannot see or interact with these services.
21
+ */
22
+ declare const PLATFORM_ADMIN_ONLY_SERVICES: readonly string[];
23
+ /**
24
+ * Standardised 7-role model (platform-wide, same in all subdomains).
25
+ * Ordered from highest to lowest privilege.
26
+ *
27
+ * platform_admin — Oplytics staff, cross-enterprise, Business Hub
28
+ * enterprise_admin — manages users/hierarchy/settings within their enterprise
29
+ * superuser — cross-functional read-write within enterprise (all hierarchy levels);
30
+ * can manage operational data but NOT users or enterprise settings
31
+ * bu_user — scoped to assigned Business Unit(s) and children
32
+ * site_user — scoped to assigned Site(s) and children
33
+ * area_user — scoped to assigned Area(s) and children
34
+ * asset_user — scoped to assigned Asset(s) only
35
+ */
36
+ declare const ALL_ROLES: readonly ["platform_admin", "enterprise_admin", "superuser", "bu_user", "site_user", "area_user", "asset_user"];
37
+ type RoleType = (typeof ALL_ROLES)[number];
38
+ /**
39
+ * Role hierarchy from lowest to highest privilege.
40
+ * Used for hasMinimumRole() checks.
41
+ */
42
+ declare const ROLE_HIERARCHY: readonly RoleType[];
43
+ /** Check if a role meets or exceeds the minimum required role */
44
+ declare function hasMinimumRole(userRole: RoleType, minimumRole: RoleType): boolean;
45
+ /** Check if a role is one of the admin roles */
46
+ declare function isAdmin(role: RoleType): boolean;
47
+ /** Check if a role is superuser-level or above */
48
+ declare function isSuperuserOrAbove(role: RoleType): boolean;
49
+ /** Roles that grant admin-level access (can manage users, hierarchy, etc.) */
50
+ declare const ADMIN_ROLES: readonly RoleType[];
51
+ /** Roles that grant superuser-level access (can manage operational data across enterprise) */
52
+ declare const SUPERUSER_ROLES: readonly RoleType[];
53
+ /** Roles that require the area level to be enabled on the enterprise */
54
+ declare const AREA_DEPENDENT_ROLES: readonly RoleType[];
55
+ /** Roles that require the asset level to be enabled on the enterprise */
56
+ declare const ASSET_DEPENDENT_ROLES: readonly RoleType[];
57
+ /** Access levels for user_access_scopes */
58
+ declare const ACCESS_LEVELS: readonly ["enterprise", "business_unit", "site", "area", "asset"];
59
+ type AccessLevelType = (typeof ACCESS_LEVELS)[number];
60
+ /** Access levels that depend on optional hierarchy toggles */
61
+ declare const AREA_DEPENDENT_ACCESS_LEVELS: readonly AccessLevelType[];
62
+ declare const ASSET_DEPENDENT_ACCESS_LEVELS: readonly AccessLevelType[];
63
+
64
+ export { ACCESS_LEVELS, ADMIN_ROLES, ALL_ROLES, AREA_DEPENDENT_ACCESS_LEVELS, AREA_DEPENDENT_ROLES, ASSET_DEPENDENT_ACCESS_LEVELS, ASSET_DEPENDENT_ROLES, AXIOS_TIMEOUT_MS, type AccessLevelType, COOKIE_NAME, NOT_ADMIN_ERR_MSG, NOT_ENTERPRISE_ADMIN_ERR_MSG, NOT_PLATFORM_ADMIN_ERR_MSG, NOT_SUPERUSER_ERR_MSG, NO_ENTERPRISE_ERR_MSG, ONE_YEAR_MS, PLATFORM_ADMIN_ONLY_SERVICES, ROLE_HIERARCHY, type RoleType, SUPERUSER_ROLES, UNAUTHED_ERR_MSG, hasMinimumRole, isAdmin, isSuperuserOrAbove };
@@ -0,0 +1,87 @@
1
+ // src/rbac/index.ts
2
+ var COOKIE_NAME = "app_session_id";
3
+ var ONE_YEAR_MS = 1e3 * 60 * 60 * 24 * 365;
4
+ var AXIOS_TIMEOUT_MS = 3e4;
5
+ var UNAUTHED_ERR_MSG = "Please login (10001)";
6
+ var NOT_ADMIN_ERR_MSG = "You do not have required permission (10002)";
7
+ var NOT_PLATFORM_ADMIN_ERR_MSG = "Platform admin access required (10003)";
8
+ var NOT_ENTERPRISE_ADMIN_ERR_MSG = "Enterprise admin access required (10004)";
9
+ var NO_ENTERPRISE_ERR_MSG = "Enterprise context not resolved. Please ensure your account is linked to an enterprise in the portal. (10005)";
10
+ var NOT_SUPERUSER_ERR_MSG = "This action requires superuser access or above (10006)";
11
+ var PLATFORM_ADMIN_ONLY_SERVICES = ["business-hub"];
12
+ var ALL_ROLES = [
13
+ "platform_admin",
14
+ "enterprise_admin",
15
+ "superuser",
16
+ "bu_user",
17
+ "site_user",
18
+ "area_user",
19
+ "asset_user"
20
+ ];
21
+ var ROLE_HIERARCHY = [
22
+ "asset_user",
23
+ "area_user",
24
+ "site_user",
25
+ "bu_user",
26
+ "superuser",
27
+ "enterprise_admin",
28
+ "platform_admin"
29
+ ];
30
+ function hasMinimumRole(userRole, minimumRole) {
31
+ return ROLE_HIERARCHY.indexOf(userRole) >= ROLE_HIERARCHY.indexOf(minimumRole);
32
+ }
33
+ function isAdmin(role) {
34
+ return ADMIN_ROLES.includes(role);
35
+ }
36
+ function isSuperuserOrAbove(role) {
37
+ return SUPERUSER_ROLES.includes(role);
38
+ }
39
+ var ADMIN_ROLES = [
40
+ "platform_admin",
41
+ "enterprise_admin"
42
+ ];
43
+ var SUPERUSER_ROLES = [
44
+ "platform_admin",
45
+ "enterprise_admin",
46
+ "superuser"
47
+ ];
48
+ var AREA_DEPENDENT_ROLES = ["area_user"];
49
+ var ASSET_DEPENDENT_ROLES = ["asset_user"];
50
+ var ACCESS_LEVELS = [
51
+ "enterprise",
52
+ "business_unit",
53
+ "site",
54
+ "area",
55
+ "asset"
56
+ ];
57
+ var AREA_DEPENDENT_ACCESS_LEVELS = [
58
+ "area"
59
+ ];
60
+ var ASSET_DEPENDENT_ACCESS_LEVELS = [
61
+ "asset"
62
+ ];
63
+ export {
64
+ ACCESS_LEVELS,
65
+ ADMIN_ROLES,
66
+ ALL_ROLES,
67
+ AREA_DEPENDENT_ACCESS_LEVELS,
68
+ AREA_DEPENDENT_ROLES,
69
+ ASSET_DEPENDENT_ACCESS_LEVELS,
70
+ ASSET_DEPENDENT_ROLES,
71
+ AXIOS_TIMEOUT_MS,
72
+ COOKIE_NAME,
73
+ NOT_ADMIN_ERR_MSG,
74
+ NOT_ENTERPRISE_ADMIN_ERR_MSG,
75
+ NOT_PLATFORM_ADMIN_ERR_MSG,
76
+ NOT_SUPERUSER_ERR_MSG,
77
+ NO_ENTERPRISE_ERR_MSG,
78
+ ONE_YEAR_MS,
79
+ PLATFORM_ADMIN_ONLY_SERVICES,
80
+ ROLE_HIERARCHY,
81
+ SUPERUSER_ROLES,
82
+ UNAUTHED_ERR_MSG,
83
+ hasMinimumRole,
84
+ isAdmin,
85
+ isSuperuserOrAbove
86
+ };
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/rbac/index.ts"],"sourcesContent":["/**\n * @oplytics/shared-ui/rbac\n *\n * Standardised Role-Based Access Control for all Oplytics.digital subdomains.\n * Single source of truth for the 7-role model, permission checks, and error messages.\n */\n\n// ─── Session & Transport Constants ───────────────────────────────────────────\n\nexport const COOKIE_NAME = \"app_session_id\";\nexport const ONE_YEAR_MS = 1000 * 60 * 60 * 24 * 365;\nexport const AXIOS_TIMEOUT_MS = 30_000;\n\n// ─── Error Message Constants ─────────────────────────────────────────────────\n\nexport const UNAUTHED_ERR_MSG = \"Please login (10001)\";\nexport const NOT_ADMIN_ERR_MSG =\n \"You do not have required permission (10002)\";\nexport const NOT_PLATFORM_ADMIN_ERR_MSG =\n \"Platform admin access required (10003)\";\nexport const NOT_ENTERPRISE_ADMIN_ERR_MSG =\n \"Enterprise admin access required (10004)\";\nexport const NO_ENTERPRISE_ERR_MSG =\n \"Enterprise context not resolved. Please ensure your account is linked to an enterprise in the portal. (10005)\";\nexport const NOT_SUPERUSER_ERR_MSG =\n \"This action requires superuser access or above (10006)\";\n\n// ─── Service Visibility ──────────────────────────────────────────────────────\n\n/**\n * Services restricted to platform_admin role only.\n * These services are NOT visible in ServiceHub, Portal, marketing pages, or footer.\n * They can only be assigned/revoked by platform_admin users.\n * Non-platform-admin users cannot see or interact with these services.\n */\nexport const PLATFORM_ADMIN_ONLY_SERVICES: readonly string[] = [\"business-hub\"];\n\n// ─── 7-Role Model ────────────────────────────────────────────────────────────\n\n/**\n * Standardised 7-role model (platform-wide, same in all subdomains).\n * Ordered from highest to lowest privilege.\n *\n * platform_admin — Oplytics staff, cross-enterprise, Business Hub\n * enterprise_admin — manages users/hierarchy/settings within their enterprise\n * superuser — cross-functional read-write within enterprise (all hierarchy levels);\n * can manage operational data but NOT users or enterprise settings\n * bu_user — scoped to assigned Business Unit(s) and children\n * site_user — scoped to assigned Site(s) and children\n * area_user — scoped to assigned Area(s) and children\n * asset_user — scoped to assigned Asset(s) only\n */\nexport const ALL_ROLES = [\n \"platform_admin\",\n \"enterprise_admin\",\n \"superuser\",\n \"bu_user\",\n \"site_user\",\n \"area_user\",\n \"asset_user\",\n] as const;\n\nexport type RoleType = (typeof ALL_ROLES)[number];\n\n/**\n * Role hierarchy from lowest to highest privilege.\n * Used for hasMinimumRole() checks.\n */\nexport const ROLE_HIERARCHY: readonly RoleType[] = [\n \"asset_user\",\n \"area_user\",\n \"site_user\",\n \"bu_user\",\n \"superuser\",\n \"enterprise_admin\",\n \"platform_admin\",\n];\n\n// ─── Permission Helpers ──────────────────────────────────────────────────────\n\n/** Check if a role meets or exceeds the minimum required role */\nexport function hasMinimumRole(\n userRole: RoleType,\n minimumRole: RoleType,\n): boolean {\n return ROLE_HIERARCHY.indexOf(userRole) >= ROLE_HIERARCHY.indexOf(minimumRole);\n}\n\n/** Check if a role is one of the admin roles */\nexport function isAdmin(role: RoleType): boolean {\n return ADMIN_ROLES.includes(role);\n}\n\n/** Check if a role is superuser-level or above */\nexport function isSuperuserOrAbove(role: RoleType): boolean {\n return SUPERUSER_ROLES.includes(role);\n}\n\n// ─── Role Groups ─────────────────────────────────────────────────────────────\n\n/** Roles that grant admin-level access (can manage users, hierarchy, etc.) */\nexport const ADMIN_ROLES: readonly RoleType[] = [\n \"platform_admin\",\n \"enterprise_admin\",\n];\n\n/** Roles that grant superuser-level access (can manage operational data across enterprise) */\nexport const SUPERUSER_ROLES: readonly RoleType[] = [\n \"platform_admin\",\n \"enterprise_admin\",\n \"superuser\",\n];\n\n/** Roles that require the area level to be enabled on the enterprise */\nexport const AREA_DEPENDENT_ROLES: readonly RoleType[] = [\"area_user\"];\n\n/** Roles that require the asset level to be enabled on the enterprise */\nexport const ASSET_DEPENDENT_ROLES: readonly RoleType[] = [\"asset_user\"];\n\n// ─── Access Levels ───────────────────────────────────────────────────────────\n\n/** Access levels for user_access_scopes */\nexport const ACCESS_LEVELS = [\n \"enterprise\",\n \"business_unit\",\n \"site\",\n \"area\",\n \"asset\",\n] as const;\n\nexport type AccessLevelType = (typeof ACCESS_LEVELS)[number];\n\n/** Access levels that depend on optional hierarchy toggles */\nexport const AREA_DEPENDENT_ACCESS_LEVELS: readonly AccessLevelType[] = [\n \"area\",\n];\nexport const ASSET_DEPENDENT_ACCESS_LEVELS: readonly AccessLevelType[] = [\n \"asset\",\n];\n"],"mappings":";AASO,IAAM,cAAc;AACpB,IAAM,cAAc,MAAO,KAAK,KAAK,KAAK;AAC1C,IAAM,mBAAmB;AAIzB,IAAM,mBAAmB;AACzB,IAAM,oBACX;AACK,IAAM,6BACX;AACK,IAAM,+BACX;AACK,IAAM,wBACX;AACK,IAAM,wBACX;AAUK,IAAM,+BAAkD,CAAC,cAAc;AAiBvE,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,IAAM,iBAAsC;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,eACd,UACA,aACS;AACT,SAAO,eAAe,QAAQ,QAAQ,KAAK,eAAe,QAAQ,WAAW;AAC/E;AAGO,SAAS,QAAQ,MAAyB;AAC/C,SAAO,YAAY,SAAS,IAAI;AAClC;AAGO,SAAS,mBAAmB,MAAyB;AAC1D,SAAO,gBAAgB,SAAS,IAAI;AACtC;AAKO,IAAM,cAAmC;AAAA,EAC9C;AAAA,EACA;AACF;AAGO,IAAM,kBAAuC;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,uBAA4C,CAAC,WAAW;AAG9D,IAAM,wBAA6C,CAAC,YAAY;AAKhE,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,+BAA2D;AAAA,EACtE;AACF;AACO,IAAM,gCAA4D;AAAA,EACvE;AACF;","names":[]}
@@ -0,0 +1,116 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ interface ReportDialogRenderProps {
5
+ isOpen: boolean;
6
+ onClose: () => void;
7
+ type: "report" | "feedback";
8
+ category: ReportCategory | FeedbackCategory;
9
+ label: string;
10
+ description: string;
11
+ color: string;
12
+ icon: React.ElementType;
13
+ onSubmit: (description: string, extra?: {
14
+ location?: string;
15
+ severity?: string;
16
+ }) => void;
17
+ isSubmitting: boolean;
18
+ }
19
+ interface ReportingToolbarProps extends ReportingToolbarConfig {
20
+ /** Compact mode — smaller buttons, icon-only on mobile */
21
+ compact?: boolean;
22
+ /** CSS class for the container */
23
+ className?: string;
24
+ /**
25
+ * Render prop for the dialog. If not provided, the toolbar only shows buttons
26
+ * and calls onReportSubmit/onFeedbackSubmit directly with a window.prompt fallback.
27
+ */
28
+ renderDialog?: (props: ReportDialogRenderProps) => ReactNode;
29
+ }
30
+ declare function ReportingToolbar({ moduleName, showIncidentReporting, showFeedback, reportCategories, feedbackCategories, onReportSubmit, onFeedbackSubmit, compact, className, renderDialog, }: ReportingToolbarProps): react_jsx_runtime.JSX.Element;
31
+
32
+ /**
33
+ * @oplytics/shared-ui/reporting
34
+ *
35
+ * Reporting and feedback toolbar types and configuration for all Oplytics subdomains.
36
+ * Provides the standard Safety/Environmental/Stop Work incident reporting buttons
37
+ * and Problem/Suggestion feedback buttons.
38
+ *
39
+ * The actual ReportingToolbar React component depends on shadcn/ui primitives
40
+ * (Dialog, Button, Textarea, Select) which vary across subdomains until
41
+ * consolidation. This module provides the types, configuration, and submission
42
+ * logic that are shared.
43
+ */
44
+ type ReportCategory = "safety" | "environmental" | "stop-work";
45
+ type FeedbackCategory = "problem" | "suggestion";
46
+ interface IncidentReport {
47
+ category: ReportCategory;
48
+ description: string;
49
+ location?: string;
50
+ severity?: "low" | "medium" | "high" | "critical";
51
+ moduleName: string;
52
+ /** ISO timestamp */
53
+ timestamp: string;
54
+ /** User who submitted */
55
+ submittedBy?: string;
56
+ /** Hierarchy context at time of submission */
57
+ hierarchyContext?: {
58
+ enterpriseId?: number;
59
+ businessUnitId?: number;
60
+ siteId?: number;
61
+ areaId?: number;
62
+ assetId?: number;
63
+ };
64
+ }
65
+ interface FeedbackReport {
66
+ category: FeedbackCategory;
67
+ description: string;
68
+ moduleName: string;
69
+ /** ISO timestamp */
70
+ timestamp: string;
71
+ /** User who submitted */
72
+ submittedBy?: string;
73
+ /** Page/route where feedback was submitted */
74
+ pageContext?: string;
75
+ }
76
+ interface ReportingToolbarConfig {
77
+ /** Service/module name (e.g., "SQDCP", "OEE Manager") */
78
+ moduleName: string;
79
+ /** Whether to show incident reporting buttons (default: true) */
80
+ showIncidentReporting?: boolean;
81
+ /** Whether to show feedback buttons (default: true) */
82
+ showFeedback?: boolean;
83
+ /** Custom report categories to show (default: all three) */
84
+ reportCategories?: ReportCategory[];
85
+ /** Custom feedback categories to show (default: both) */
86
+ feedbackCategories?: FeedbackCategory[];
87
+ /** Handler called when an incident report is submitted */
88
+ onReportSubmit: (report: IncidentReport) => Promise<void> | void;
89
+ /** Handler called when feedback is submitted */
90
+ onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;
91
+ }
92
+ interface ReportButtonDef {
93
+ category: ReportCategory;
94
+ label: string;
95
+ iconName: string;
96
+ color: string;
97
+ description: string;
98
+ }
99
+ interface FeedbackButtonDef {
100
+ category: FeedbackCategory;
101
+ label: string;
102
+ iconName: string;
103
+ color: string;
104
+ description: string;
105
+ }
106
+ /** Standard incident report buttons — consistent across all subdomains */
107
+ declare const REPORT_BUTTONS: ReportButtonDef[];
108
+ /** Standard feedback buttons — consistent across all subdomains */
109
+ declare const FEEDBACK_BUTTONS: FeedbackButtonDef[];
110
+ /** Create a default ReportingToolbarConfig with sensible defaults */
111
+ declare function createReportingConfig(moduleName: string, handlers: {
112
+ onReportSubmit: (report: IncidentReport) => Promise<void> | void;
113
+ onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;
114
+ }): ReportingToolbarConfig;
115
+
116
+ export { FEEDBACK_BUTTONS, type FeedbackButtonDef, type FeedbackCategory, type FeedbackReport, type IncidentReport, REPORT_BUTTONS, type ReportButtonDef, type ReportCategory, type ReportDialogRenderProps, ReportingToolbar, type ReportingToolbarConfig, type ReportingToolbarProps, createReportingConfig };
@@ -0,0 +1,258 @@
1
+ import {
2
+ cn
3
+ } from "../chunk-JT3XLKKD.js";
4
+
5
+ // src/reporting/ReportingToolbar.tsx
6
+ import {
7
+ ShieldAlert,
8
+ Leaf,
9
+ OctagonX,
10
+ AlertTriangle,
11
+ Lightbulb
12
+ } from "lucide-react";
13
+ import { useState, useCallback } from "react";
14
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
+ var REPORT_ICONS = {
16
+ safety: ShieldAlert,
17
+ environmental: Leaf,
18
+ "stop-work": OctagonX
19
+ };
20
+ var FEEDBACK_ICONS = {
21
+ problem: AlertTriangle,
22
+ suggestion: Lightbulb
23
+ };
24
+ var REPORT_COLORS = {
25
+ safety: "#ef4444",
26
+ environmental: "#22c55e",
27
+ "stop-work": "#f59e0b"
28
+ };
29
+ var FEEDBACK_COLORS = {
30
+ problem: "#ef4444",
31
+ suggestion: "#8C34E9"
32
+ };
33
+ var REPORT_LABELS = {
34
+ safety: "Safety",
35
+ environmental: "Environmental",
36
+ "stop-work": "Stop Work"
37
+ };
38
+ var FEEDBACK_LABELS = {
39
+ problem: "Problem",
40
+ suggestion: "Suggestion"
41
+ };
42
+ var REPORT_DESCRIPTIONS = {
43
+ safety: "Report a safety incident, near-miss, or hazard",
44
+ environmental: "Report an environmental incident or concern",
45
+ "stop-work": "Raise a stop work authority \u2014 immediate safety concern"
46
+ };
47
+ var FEEDBACK_DESCRIPTIONS = {
48
+ problem: "Report a problem with the platform",
49
+ suggestion: "Suggest an improvement or new feature"
50
+ };
51
+ function ToolbarButton({
52
+ icon: Icon,
53
+ label,
54
+ color,
55
+ compact,
56
+ onClick
57
+ }) {
58
+ return /* @__PURE__ */ jsxs(
59
+ "button",
60
+ {
61
+ onClick,
62
+ className: cn(
63
+ "flex items-center gap-1.5 rounded-md transition-all duration-200",
64
+ "outline-none focus-visible:ring-1 focus-visible:ring-[#8C34E9]",
65
+ "hover:opacity-90 cursor-pointer",
66
+ compact ? "px-2 py-1" : "px-2.5 py-1.5"
67
+ ),
68
+ style: {
69
+ backgroundColor: `${color}15`,
70
+ color,
71
+ border: `1px solid ${color}30`
72
+ },
73
+ title: label,
74
+ children: [
75
+ /* @__PURE__ */ jsx(Icon, { className: cn("shrink-0", compact ? "h-3.5 w-3.5" : "h-4 w-4") }),
76
+ !compact && /* @__PURE__ */ jsx("span", { className: cn("text-xs font-medium", compact ? "hidden sm:inline" : ""), children: label })
77
+ ]
78
+ }
79
+ );
80
+ }
81
+ function ReportingToolbar({
82
+ moduleName,
83
+ showIncidentReporting = true,
84
+ showFeedback = true,
85
+ reportCategories = ["safety", "environmental", "stop-work"],
86
+ feedbackCategories = ["problem", "suggestion"],
87
+ onReportSubmit,
88
+ onFeedbackSubmit,
89
+ compact = false,
90
+ className,
91
+ renderDialog
92
+ }) {
93
+ const [activeDialog, setActiveDialog] = useState(null);
94
+ const [isSubmitting, setIsSubmitting] = useState(false);
95
+ const openDialog = useCallback(
96
+ (type, category) => {
97
+ if (renderDialog) {
98
+ setActiveDialog({ type, category });
99
+ } else {
100
+ const description = window.prompt(
101
+ type === "report" ? `Describe the ${category} incident:` : `Describe your ${category}:`
102
+ );
103
+ if (description) {
104
+ if (type === "report") {
105
+ onReportSubmit({
106
+ category,
107
+ description,
108
+ moduleName,
109
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
110
+ });
111
+ } else {
112
+ onFeedbackSubmit({
113
+ category,
114
+ description,
115
+ moduleName,
116
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
117
+ pageContext: typeof window !== "undefined" ? window.location.pathname : void 0
118
+ });
119
+ }
120
+ }
121
+ }
122
+ },
123
+ [renderDialog, moduleName, onReportSubmit, onFeedbackSubmit]
124
+ );
125
+ const closeDialog = useCallback(() => {
126
+ setActiveDialog(null);
127
+ setIsSubmitting(false);
128
+ }, []);
129
+ const handleSubmit = useCallback(
130
+ async (description, extra) => {
131
+ if (!activeDialog) return;
132
+ setIsSubmitting(true);
133
+ try {
134
+ if (activeDialog.type === "report") {
135
+ await onReportSubmit({
136
+ category: activeDialog.category,
137
+ description,
138
+ location: extra?.location,
139
+ severity: extra?.severity,
140
+ moduleName,
141
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
142
+ });
143
+ } else {
144
+ await onFeedbackSubmit({
145
+ category: activeDialog.category,
146
+ description,
147
+ moduleName,
148
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
149
+ pageContext: typeof window !== "undefined" ? window.location.pathname : void 0
150
+ });
151
+ }
152
+ closeDialog();
153
+ } catch (err) {
154
+ console.error("[ReportingToolbar] Submit failed:", err);
155
+ setIsSubmitting(false);
156
+ }
157
+ },
158
+ [activeDialog, moduleName, onReportSubmit, onFeedbackSubmit, closeDialog]
159
+ );
160
+ const dialogProps = activeDialog ? {
161
+ isOpen: true,
162
+ onClose: closeDialog,
163
+ type: activeDialog.type,
164
+ category: activeDialog.category,
165
+ label: activeDialog.type === "report" ? REPORT_LABELS[activeDialog.category] : FEEDBACK_LABELS[activeDialog.category],
166
+ description: activeDialog.type === "report" ? REPORT_DESCRIPTIONS[activeDialog.category] : FEEDBACK_DESCRIPTIONS[activeDialog.category],
167
+ color: activeDialog.type === "report" ? REPORT_COLORS[activeDialog.category] : FEEDBACK_COLORS[activeDialog.category],
168
+ icon: activeDialog.type === "report" ? REPORT_ICONS[activeDialog.category] : FEEDBACK_ICONS[activeDialog.category],
169
+ onSubmit: handleSubmit,
170
+ isSubmitting
171
+ } : null;
172
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
173
+ /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-1.5", className), children: [
174
+ showIncidentReporting && reportCategories.map((cat) => /* @__PURE__ */ jsx(
175
+ ToolbarButton,
176
+ {
177
+ icon: REPORT_ICONS[cat],
178
+ label: REPORT_LABELS[cat],
179
+ color: REPORT_COLORS[cat],
180
+ compact,
181
+ onClick: () => openDialog("report", cat)
182
+ },
183
+ cat
184
+ )),
185
+ showIncidentReporting && showFeedback && /* @__PURE__ */ jsx("div", { className: "w-px h-5 bg-[#1E2738] mx-1" }),
186
+ showFeedback && feedbackCategories.map((cat) => /* @__PURE__ */ jsx(
187
+ ToolbarButton,
188
+ {
189
+ icon: FEEDBACK_ICONS[cat],
190
+ label: FEEDBACK_LABELS[cat],
191
+ color: FEEDBACK_COLORS[cat],
192
+ compact,
193
+ onClick: () => openDialog("feedback", cat)
194
+ },
195
+ cat
196
+ ))
197
+ ] }),
198
+ renderDialog && dialogProps && renderDialog(dialogProps)
199
+ ] });
200
+ }
201
+
202
+ // src/reporting/index.ts
203
+ var REPORT_BUTTONS = [
204
+ {
205
+ category: "safety",
206
+ label: "Safety",
207
+ iconName: "ShieldAlert",
208
+ color: "#ef4444",
209
+ description: "Report a safety incident, near-miss, or hazard"
210
+ },
211
+ {
212
+ category: "environmental",
213
+ label: "Environmental",
214
+ iconName: "Leaf",
215
+ color: "#22c55e",
216
+ description: "Report an environmental incident or concern"
217
+ },
218
+ {
219
+ category: "stop-work",
220
+ label: "Stop Work",
221
+ iconName: "OctagonX",
222
+ color: "#f59e0b",
223
+ description: "Raise a stop work authority \u2014 immediate safety concern"
224
+ }
225
+ ];
226
+ var FEEDBACK_BUTTONS = [
227
+ {
228
+ category: "problem",
229
+ label: "Problem",
230
+ iconName: "AlertTriangle",
231
+ color: "#ef4444",
232
+ description: "Report a problem with the platform"
233
+ },
234
+ {
235
+ category: "suggestion",
236
+ label: "Suggestion",
237
+ iconName: "Lightbulb",
238
+ color: "#8C34E9",
239
+ description: "Suggest an improvement or new feature"
240
+ }
241
+ ];
242
+ function createReportingConfig(moduleName, handlers) {
243
+ return {
244
+ moduleName,
245
+ showIncidentReporting: true,
246
+ showFeedback: true,
247
+ reportCategories: ["safety", "environmental", "stop-work"],
248
+ feedbackCategories: ["problem", "suggestion"],
249
+ ...handlers
250
+ };
251
+ }
252
+ export {
253
+ FEEDBACK_BUTTONS,
254
+ REPORT_BUTTONS,
255
+ ReportingToolbar,
256
+ createReportingConfig
257
+ };
258
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/reporting/ReportingToolbar.tsx","../../src/reporting/index.ts"],"sourcesContent":["/**\n * ReportingToolbar — standard Safety/Environmental/Stop Work incident reporting\n * and Problem/Suggestion feedback buttons for all Oplytics subdomains.\n *\n * This is a headless-ish component: it renders the buttons and manages dialog state,\n * but delegates the actual dialog rendering to a render prop so consuming apps\n * can use their own shadcn/ui Dialog components.\n *\n * For apps that want a fully self-contained toolbar, use ReportingToolbarStandalone\n * which includes basic HTML dialogs.\n *\n * Oplytics dark theme: #0A0E1A bg, #8C34E9 accent\n */\nimport { cn } from \"../utils/cn\";\nimport {\n ShieldAlert,\n Leaf,\n OctagonX,\n AlertTriangle,\n Lightbulb,\n} from \"lucide-react\";\nimport { useState, useCallback, type ReactNode } from \"react\";\nimport type {\n ReportCategory,\n FeedbackCategory,\n IncidentReport,\n FeedbackReport,\n ReportingToolbarConfig,\n} from \"./index\";\n\n/* ── Icon map ── */\n\nconst REPORT_ICONS: Record<ReportCategory, React.ElementType> = {\n safety: ShieldAlert,\n environmental: Leaf,\n \"stop-work\": OctagonX,\n};\n\nconst FEEDBACK_ICONS: Record<FeedbackCategory, React.ElementType> = {\n problem: AlertTriangle,\n suggestion: Lightbulb,\n};\n\nconst REPORT_COLORS: Record<ReportCategory, string> = {\n safety: \"#ef4444\",\n environmental: \"#22c55e\",\n \"stop-work\": \"#f59e0b\",\n};\n\nconst FEEDBACK_COLORS: Record<FeedbackCategory, string> = {\n problem: \"#ef4444\",\n suggestion: \"#8C34E9\",\n};\n\nconst REPORT_LABELS: Record<ReportCategory, string> = {\n safety: \"Safety\",\n environmental: \"Environmental\",\n \"stop-work\": \"Stop Work\",\n};\n\nconst FEEDBACK_LABELS: Record<FeedbackCategory, string> = {\n problem: \"Problem\",\n suggestion: \"Suggestion\",\n};\n\nconst REPORT_DESCRIPTIONS: Record<ReportCategory, string> = {\n safety: \"Report a safety incident, near-miss, or hazard\",\n environmental: \"Report an environmental incident or concern\",\n \"stop-work\": \"Raise a stop work authority — immediate safety concern\",\n};\n\nconst FEEDBACK_DESCRIPTIONS: Record<FeedbackCategory, string> = {\n problem: \"Report a problem with the platform\",\n suggestion: \"Suggest an improvement or new feature\",\n};\n\n/* ── Dialog render prop types ── */\n\nexport interface ReportDialogRenderProps {\n isOpen: boolean;\n onClose: () => void;\n type: \"report\" | \"feedback\";\n category: ReportCategory | FeedbackCategory;\n label: string;\n description: string;\n color: string;\n icon: React.ElementType;\n onSubmit: (description: string, extra?: { location?: string; severity?: string }) => void;\n isSubmitting: boolean;\n}\n\n/* ── Toolbar button ── */\n\nfunction ToolbarButton({\n icon: Icon,\n label,\n color,\n compact,\n onClick,\n}: {\n icon: React.ElementType;\n label: string;\n color: string;\n compact?: boolean;\n onClick: () => void;\n}) {\n return (\n <button\n onClick={onClick}\n className={cn(\n \"flex items-center gap-1.5 rounded-md transition-all duration-200\",\n \"outline-none focus-visible:ring-1 focus-visible:ring-[#8C34E9]\",\n \"hover:opacity-90 cursor-pointer\",\n compact ? \"px-2 py-1\" : \"px-2.5 py-1.5\"\n )}\n style={{\n backgroundColor: `${color}15`,\n color: color,\n border: `1px solid ${color}30`,\n }}\n title={label}\n >\n <Icon className={cn(\"shrink-0\", compact ? \"h-3.5 w-3.5\" : \"h-4 w-4\")} />\n {!compact && (\n <span className={cn(\"text-xs font-medium\", compact ? \"hidden sm:inline\" : \"\")}>\n {label}\n </span>\n )}\n </button>\n );\n}\n\n/* ── Main ReportingToolbar ── */\n\nexport interface ReportingToolbarProps extends ReportingToolbarConfig {\n /** Compact mode — smaller buttons, icon-only on mobile */\n compact?: boolean;\n /** CSS class for the container */\n className?: string;\n /**\n * Render prop for the dialog. If not provided, the toolbar only shows buttons\n * and calls onReportSubmit/onFeedbackSubmit directly with a window.prompt fallback.\n */\n renderDialog?: (props: ReportDialogRenderProps) => ReactNode;\n}\n\nexport function ReportingToolbar({\n moduleName,\n showIncidentReporting = true,\n showFeedback = true,\n reportCategories = [\"safety\", \"environmental\", \"stop-work\"],\n feedbackCategories = [\"problem\", \"suggestion\"],\n onReportSubmit,\n onFeedbackSubmit,\n compact = false,\n className,\n renderDialog,\n}: ReportingToolbarProps) {\n const [activeDialog, setActiveDialog] = useState<{\n type: \"report\" | \"feedback\";\n category: ReportCategory | FeedbackCategory;\n } | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const openDialog = useCallback(\n (type: \"report\" | \"feedback\", category: ReportCategory | FeedbackCategory) => {\n if (renderDialog) {\n setActiveDialog({ type, category });\n } else {\n // Fallback: use window.prompt\n const description = window.prompt(\n type === \"report\"\n ? `Describe the ${category} incident:`\n : `Describe your ${category}:`\n );\n if (description) {\n if (type === \"report\") {\n onReportSubmit({\n category: category as ReportCategory,\n description,\n moduleName,\n timestamp: new Date().toISOString(),\n });\n } else {\n onFeedbackSubmit({\n category: category as FeedbackCategory,\n description,\n moduleName,\n timestamp: new Date().toISOString(),\n pageContext: typeof window !== \"undefined\" ? window.location.pathname : undefined,\n });\n }\n }\n }\n },\n [renderDialog, moduleName, onReportSubmit, onFeedbackSubmit]\n );\n\n const closeDialog = useCallback(() => {\n setActiveDialog(null);\n setIsSubmitting(false);\n }, []);\n\n const handleSubmit = useCallback(\n async (description: string, extra?: { location?: string; severity?: string }) => {\n if (!activeDialog) return;\n setIsSubmitting(true);\n try {\n if (activeDialog.type === \"report\") {\n await onReportSubmit({\n category: activeDialog.category as ReportCategory,\n description,\n location: extra?.location,\n severity: extra?.severity as IncidentReport[\"severity\"],\n moduleName,\n timestamp: new Date().toISOString(),\n });\n } else {\n await onFeedbackSubmit({\n category: activeDialog.category as FeedbackCategory,\n description,\n moduleName,\n timestamp: new Date().toISOString(),\n pageContext: typeof window !== \"undefined\" ? window.location.pathname : undefined,\n });\n }\n closeDialog();\n } catch (err) {\n console.error(\"[ReportingToolbar] Submit failed:\", err);\n setIsSubmitting(false);\n }\n },\n [activeDialog, moduleName, onReportSubmit, onFeedbackSubmit, closeDialog]\n );\n\n // Build dialog render props\n const dialogProps: ReportDialogRenderProps | null = activeDialog\n ? {\n isOpen: true,\n onClose: closeDialog,\n type: activeDialog.type,\n category: activeDialog.category,\n label:\n activeDialog.type === \"report\"\n ? REPORT_LABELS[activeDialog.category as ReportCategory]\n : FEEDBACK_LABELS[activeDialog.category as FeedbackCategory],\n description:\n activeDialog.type === \"report\"\n ? REPORT_DESCRIPTIONS[activeDialog.category as ReportCategory]\n : FEEDBACK_DESCRIPTIONS[activeDialog.category as FeedbackCategory],\n color:\n activeDialog.type === \"report\"\n ? REPORT_COLORS[activeDialog.category as ReportCategory]\n : FEEDBACK_COLORS[activeDialog.category as FeedbackCategory],\n icon:\n activeDialog.type === \"report\"\n ? REPORT_ICONS[activeDialog.category as ReportCategory]\n : FEEDBACK_ICONS[activeDialog.category as FeedbackCategory],\n onSubmit: handleSubmit,\n isSubmitting,\n }\n : null;\n\n return (\n <>\n <div className={cn(\"flex items-center gap-1.5\", className)}>\n {/* Incident report buttons */}\n {showIncidentReporting &&\n reportCategories.map((cat) => (\n <ToolbarButton\n key={cat}\n icon={REPORT_ICONS[cat]}\n label={REPORT_LABELS[cat]}\n color={REPORT_COLORS[cat]}\n compact={compact}\n onClick={() => openDialog(\"report\", cat)}\n />\n ))}\n\n {/* Separator */}\n {showIncidentReporting && showFeedback && (\n <div className=\"w-px h-5 bg-[#1E2738] mx-1\" />\n )}\n\n {/* Feedback buttons */}\n {showFeedback &&\n feedbackCategories.map((cat) => (\n <ToolbarButton\n key={cat}\n icon={FEEDBACK_ICONS[cat]}\n label={FEEDBACK_LABELS[cat]}\n color={FEEDBACK_COLORS[cat]}\n compact={compact}\n onClick={() => openDialog(\"feedback\", cat)}\n />\n ))}\n </div>\n\n {/* Render dialog via render prop */}\n {renderDialog && dialogProps && renderDialog(dialogProps)}\n </>\n );\n}\n","/**\n * @oplytics/shared-ui/reporting\n *\n * Reporting and feedback toolbar types and configuration for all Oplytics subdomains.\n * Provides the standard Safety/Environmental/Stop Work incident reporting buttons\n * and Problem/Suggestion feedback buttons.\n *\n * The actual ReportingToolbar React component depends on shadcn/ui primitives\n * (Dialog, Button, Textarea, Select) which vary across subdomains until\n * consolidation. This module provides the types, configuration, and submission\n * logic that are shared.\n */\n\n// ─── Report Types ────────────────────────────────────────────────────────────\n\nexport type ReportCategory = \"safety\" | \"environmental\" | \"stop-work\";\nexport type FeedbackCategory = \"problem\" | \"suggestion\";\n\nexport interface IncidentReport {\n category: ReportCategory;\n description: string;\n location?: string;\n severity?: \"low\" | \"medium\" | \"high\" | \"critical\";\n moduleName: string;\n /** ISO timestamp */\n timestamp: string;\n /** User who submitted */\n submittedBy?: string;\n /** Hierarchy context at time of submission */\n hierarchyContext?: {\n enterpriseId?: number;\n businessUnitId?: number;\n siteId?: number;\n areaId?: number;\n assetId?: number;\n };\n}\n\nexport interface FeedbackReport {\n category: FeedbackCategory;\n description: string;\n moduleName: string;\n /** ISO timestamp */\n timestamp: string;\n /** User who submitted */\n submittedBy?: string;\n /** Page/route where feedback was submitted */\n pageContext?: string;\n}\n\n// ─── Toolbar Configuration ───────────────────────────────────────────────────\n\nexport interface ReportingToolbarConfig {\n /** Service/module name (e.g., \"SQDCP\", \"OEE Manager\") */\n moduleName: string;\n /** Whether to show incident reporting buttons (default: true) */\n showIncidentReporting?: boolean;\n /** Whether to show feedback buttons (default: true) */\n showFeedback?: boolean;\n /** Custom report categories to show (default: all three) */\n reportCategories?: ReportCategory[];\n /** Custom feedback categories to show (default: both) */\n feedbackCategories?: FeedbackCategory[];\n /** Handler called when an incident report is submitted */\n onReportSubmit: (report: IncidentReport) => Promise<void> | void;\n /** Handler called when feedback is submitted */\n onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;\n}\n\n// ─── Report Button Definitions ───────────────────────────────────────────────\n\nexport interface ReportButtonDef {\n category: ReportCategory;\n label: string;\n iconName: string;\n color: string;\n description: string;\n}\n\nexport interface FeedbackButtonDef {\n category: FeedbackCategory;\n label: string;\n iconName: string;\n color: string;\n description: string;\n}\n\n/** Standard incident report buttons — consistent across all subdomains */\nexport const REPORT_BUTTONS: ReportButtonDef[] = [\n {\n category: \"safety\",\n label: \"Safety\",\n iconName: \"ShieldAlert\",\n color: \"#ef4444\",\n description: \"Report a safety incident, near-miss, or hazard\",\n },\n {\n category: \"environmental\",\n label: \"Environmental\",\n iconName: \"Leaf\",\n color: \"#22c55e\",\n description: \"Report an environmental incident or concern\",\n },\n {\n category: \"stop-work\",\n label: \"Stop Work\",\n iconName: \"OctagonX\",\n color: \"#f59e0b\",\n description: \"Raise a stop work authority — immediate safety concern\",\n },\n];\n\n/** Standard feedback buttons — consistent across all subdomains */\nexport const FEEDBACK_BUTTONS: FeedbackButtonDef[] = [\n {\n category: \"problem\",\n label: \"Problem\",\n iconName: \"AlertTriangle\",\n color: \"#ef4444\",\n description: \"Report a problem with the platform\",\n },\n {\n category: \"suggestion\",\n label: \"Suggestion\",\n iconName: \"Lightbulb\",\n color: \"#8C34E9\",\n description: \"Suggest an improvement or new feature\",\n },\n];\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Create a default ReportingToolbarConfig with sensible defaults */\nexport function createReportingConfig(\n moduleName: string,\n handlers: {\n onReportSubmit: (report: IncidentReport) => Promise<void> | void;\n onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;\n },\n): ReportingToolbarConfig {\n return {\n moduleName,\n showIncidentReporting: true,\n showFeedback: true,\n reportCategories: [\"safety\", \"environmental\", \"stop-work\"],\n feedbackCategories: [\"problem\", \"suggestion\"],\n ...handlers,\n };\n}\n\n// ─── ReportingToolbar Component ─────────────────────────────────────────────\n\nexport {\n ReportingToolbar,\n type ReportingToolbarProps,\n type ReportDialogRenderProps,\n} from \"./ReportingToolbar\";\n"],"mappings":";;;;;AAcA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,UAAU,mBAAmC;AAsFlD,SA6JA,UA9IE,KAfF;AA3EJ,IAAM,eAA0D;AAAA,EAC9D,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,aAAa;AACf;AAEA,IAAM,iBAA8D;AAAA,EAClE,SAAS;AAAA,EACT,YAAY;AACd;AAEA,IAAM,gBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,aAAa;AACf;AAEA,IAAM,kBAAoD;AAAA,EACxD,SAAS;AAAA,EACT,YAAY;AACd;AAEA,IAAM,gBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,aAAa;AACf;AAEA,IAAM,kBAAoD;AAAA,EACxD,SAAS;AAAA,EACT,YAAY;AACd;AAEA,IAAM,sBAAsD;AAAA,EAC1D,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,aAAa;AACf;AAEA,IAAM,wBAA0D;AAAA,EAC9D,SAAS;AAAA,EACT,YAAY;AACd;AAmBA,SAAS,cAAc;AAAA,EACrB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU,cAAc;AAAA,MAC1B;AAAA,MACA,OAAO;AAAA,QACL,iBAAiB,GAAG,KAAK;AAAA,QACzB;AAAA,QACA,QAAQ,aAAa,KAAK;AAAA,MAC5B;AAAA,MACA,OAAO;AAAA,MAEP;AAAA,4BAAC,QAAK,WAAW,GAAG,YAAY,UAAU,gBAAgB,SAAS,GAAG;AAAA,QACrE,CAAC,WACA,oBAAC,UAAK,WAAW,GAAG,uBAAuB,UAAU,qBAAqB,EAAE,GACzE,iBACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAgBO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,wBAAwB;AAAA,EACxB,eAAe;AAAA,EACf,mBAAmB,CAAC,UAAU,iBAAiB,WAAW;AAAA,EAC1D,qBAAqB,CAAC,WAAW,YAAY;AAAA,EAC7C;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,CAAC,cAAc,eAAe,IAAI,SAG9B,IAAI;AACd,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAEtD,QAAM,aAAa;AAAA,IACjB,CAAC,MAA6B,aAAgD;AAC5E,UAAI,cAAc;AAChB,wBAAgB,EAAE,MAAM,SAAS,CAAC;AAAA,MACpC,OAAO;AAEL,cAAM,cAAc,OAAO;AAAA,UACzB,SAAS,WACL,gBAAgB,QAAQ,eACxB,iBAAiB,QAAQ;AAAA,QAC/B;AACA,YAAI,aAAa;AACf,cAAI,SAAS,UAAU;AACrB,2BAAe;AAAA,cACb;AAAA,cACA;AAAA,cACA;AAAA,cACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,YACpC,CAAC;AAAA,UACH,OAAO;AACL,6BAAiB;AAAA,cACf;AAAA,cACA;AAAA,cACA;AAAA,cACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,cAClC,aAAa,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,YAC1E,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,cAAc,YAAY,gBAAgB,gBAAgB;AAAA,EAC7D;AAEA,QAAM,cAAc,YAAY,MAAM;AACpC,oBAAgB,IAAI;AACpB,oBAAgB,KAAK;AAAA,EACvB,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe;AAAA,IACnB,OAAO,aAAqB,UAAqD;AAC/E,UAAI,CAAC,aAAc;AACnB,sBAAgB,IAAI;AACpB,UAAI;AACF,YAAI,aAAa,SAAS,UAAU;AAClC,gBAAM,eAAe;AAAA,YACnB,UAAU,aAAa;AAAA,YACvB;AAAA,YACA,UAAU,OAAO;AAAA,YACjB,UAAU,OAAO;AAAA,YACjB;AAAA,YACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,UACpC,CAAC;AAAA,QACH,OAAO;AACL,gBAAM,iBAAiB;AAAA,YACrB,UAAU,aAAa;AAAA,YACvB;AAAA,YACA;AAAA,YACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,YAClC,aAAa,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,UAC1E,CAAC;AAAA,QACH;AACA,oBAAY;AAAA,MACd,SAAS,KAAK;AACZ,gBAAQ,MAAM,qCAAqC,GAAG;AACtD,wBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,cAAc,YAAY,gBAAgB,kBAAkB,WAAW;AAAA,EAC1E;AAGA,QAAM,cAA8C,eAChD;AAAA,IACE,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM,aAAa;AAAA,IACnB,UAAU,aAAa;AAAA,IACvB,OACE,aAAa,SAAS,WAClB,cAAc,aAAa,QAA0B,IACrD,gBAAgB,aAAa,QAA4B;AAAA,IAC/D,aACE,aAAa,SAAS,WAClB,oBAAoB,aAAa,QAA0B,IAC3D,sBAAsB,aAAa,QAA4B;AAAA,IACrE,OACE,aAAa,SAAS,WAClB,cAAc,aAAa,QAA0B,IACrD,gBAAgB,aAAa,QAA4B;AAAA,IAC/D,MACE,aAAa,SAAS,WAClB,aAAa,aAAa,QAA0B,IACpD,eAAe,aAAa,QAA4B;AAAA,IAC9D,UAAU;AAAA,IACV;AAAA,EACF,IACA;AAEJ,SACE,iCACE;AAAA,yBAAC,SAAI,WAAW,GAAG,6BAA6B,SAAS,GAEtD;AAAA,+BACC,iBAAiB,IAAI,CAAC,QACpB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAM,aAAa,GAAG;AAAA,UACtB,OAAO,cAAc,GAAG;AAAA,UACxB,OAAO,cAAc,GAAG;AAAA,UACxB;AAAA,UACA,SAAS,MAAM,WAAW,UAAU,GAAG;AAAA;AAAA,QALlC;AAAA,MAMP,CACD;AAAA,MAGF,yBAAyB,gBACxB,oBAAC,SAAI,WAAU,8BAA6B;AAAA,MAI7C,gBACC,mBAAmB,IAAI,CAAC,QACtB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAM,eAAe,GAAG;AAAA,UACxB,OAAO,gBAAgB,GAAG;AAAA,UAC1B,OAAO,gBAAgB,GAAG;AAAA,UAC1B;AAAA,UACA,SAAS,MAAM,WAAW,YAAY,GAAG;AAAA;AAAA,QALpC;AAAA,MAMP,CACD;AAAA,OACL;AAAA,IAGC,gBAAgB,eAAe,aAAa,WAAW;AAAA,KAC1D;AAEJ;;;ACtNO,IAAM,iBAAoC;AAAA,EAC/C;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AACF;AAGO,IAAM,mBAAwC;AAAA,EACnD;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AACF;AAKO,SAAS,sBACd,YACA,UAIwB;AACxB,SAAO;AAAA,IACL;AAAA,IACA,uBAAuB;AAAA,IACvB,cAAc;AAAA,IACd,kBAAkB,CAAC,UAAU,iBAAiB,WAAW;AAAA,IACzD,oBAAoB,CAAC,WAAW,YAAY;AAAA,IAC5C,GAAG;AAAA,EACL;AACF;","names":[]}