pixelize-design-library 2.3.1-beta.2 → 2.3.1-beta.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.
Files changed (165) hide show
  1. package/.claude/settings.local.json +28 -1
  2. package/.cursor/TASK-SETUP.md +43 -0
  3. package/.cursor/agents/be-impl.md +37 -0
  4. package/.cursor/agents/fe-impl.md +39 -0
  5. package/.cursor/agents/task-plan.md +56 -0
  6. package/.cursor/agents/test-create.md +31 -0
  7. package/.cursor/agents/test-exec.md +26 -0
  8. package/.cursor/hooks/task-hint.env +1 -0
  9. package/.cursor/hooks/task-skill-nudge.sh +71 -0
  10. package/.cursor/hooks/task-slash-guard.sh +31 -0
  11. package/.cursor/hooks.json +13 -0
  12. package/.cursor/modules/account-management/MODULE.md +16 -0
  13. package/.cursor/modules/buttons/MODULE.md +13 -0
  14. package/.cursor/modules/cards/MODULE.md +13 -0
  15. package/.cursor/modules/charts/MODULE.md +13 -0
  16. package/.cursor/modules/common/MODULE.md +13 -0
  17. package/.cursor/modules/contact-auth/MODULE.md +13 -0
  18. package/.cursor/modules/data-display/MODULE.md +13 -0
  19. package/.cursor/modules/feedback/MODULE.md +14 -0
  20. package/.cursor/modules/form/MODULE.md +13 -0
  21. package/.cursor/modules/inputs-basic/MODULE.md +13 -0
  22. package/.cursor/modules/inputs-date-file/MODULE.md +19 -0
  23. package/.cursor/modules/inputs-select/MODULE.md +14 -0
  24. package/.cursor/modules/inputs-toggle/MODULE.md +13 -0
  25. package/.cursor/modules/kanban/MODULE.md +14 -0
  26. package/.cursor/modules/layout-navigation/MODULE.md +14 -0
  27. package/.cursor/modules/overlays/MODULE.md +13 -0
  28. package/.cursor/modules/playground/MODULE.md +15 -0
  29. package/.cursor/modules/table/MODULE.md +15 -0
  30. package/.cursor/modules/theme/MODULE.md +15 -0
  31. package/.cursor/modules/types-exports/MODULE.md +17 -0
  32. package/.cursor/modules/utility-ui/MODULE.md +15 -0
  33. package/.cursor/modules/utils-hooks/MODULE.md +13 -0
  34. package/.cursor/pixelize-task-statusline.sh +64 -0
  35. package/.cursor/plans/blocked/.gitkeep +0 -0
  36. package/.cursor/plans/current.md +35 -0
  37. package/.cursor/plans/done/.gitkeep +0 -0
  38. package/.cursor/rules +31 -0
  39. package/.cursor/skills/task/SKILL.md +167 -0
  40. package/CLAUDE.md +122 -0
  41. package/dist/Components/Accordion/Accordion.js +26 -5
  42. package/dist/Components/Card/PaymentCard/PaymentCard.d.ts +1 -1
  43. package/dist/Components/Card/PaymentCard/PaymentCard.js +3 -3
  44. package/dist/Components/Card/PaymentCard/PaymentCardProps.d.ts +1 -0
  45. package/dist/Components/CopyButton/CopyButton.d.ts +22 -0
  46. package/dist/Components/CopyButton/CopyButton.js +126 -0
  47. package/dist/Components/CustomModulesTable/CustomModulesTable.d.ts +4 -0
  48. package/dist/Components/CustomModulesTable/CustomModulesTable.js +182 -0
  49. package/dist/Components/CustomModulesTable/CustomModulesTable.test.d.ts +1 -0
  50. package/dist/Components/CustomModulesTable/CustomModulesTable.test.js +84 -0
  51. package/dist/Components/CustomModulesTable/CustomModulesTableProps.d.ts +54 -0
  52. package/dist/Components/CustomModulesTable/CustomModulesTableProps.js +2 -0
  53. package/dist/Components/CustomModulesTable/DeleteModuleModal.d.ts +4 -0
  54. package/dist/Components/CustomModulesTable/DeleteModuleModal.js +33 -0
  55. package/dist/Components/CustomModulesTable/EditModuleModal.d.ts +4 -0
  56. package/dist/Components/CustomModulesTable/EditModuleModal.js +63 -0
  57. package/dist/Components/Dropdown/DropDown.js +110 -28
  58. package/dist/Components/Dropdown/Dropdown.test.d.ts +1 -0
  59. package/dist/Components/Dropdown/Dropdown.test.js +102 -0
  60. package/dist/Components/Dropdown/DropdownProps.d.ts +4 -1
  61. package/dist/Components/EmptyState/EmptyState.d.ts +4 -0
  62. package/dist/Components/EmptyState/EmptyState.js +65 -0
  63. package/dist/Components/EmptyState/EmptyStateProps.d.ts +28 -0
  64. package/dist/Components/EmptyState/EmptyStateProps.js +2 -0
  65. package/dist/Components/FieldSelectModal/FieldSelectModal.d.ts +26 -0
  66. package/dist/Components/FieldSelectModal/FieldSelectModal.js +107 -0
  67. package/dist/Components/FilePreview/FilePreview.d.ts +6 -0
  68. package/dist/Components/FilePreview/FilePreview.js +190 -0
  69. package/dist/Components/FilePreview/FilePreviewProps.d.ts +26 -0
  70. package/dist/Components/FilePreview/FilePreviewProps.js +2 -0
  71. package/dist/Components/KanbanBoard/AccountCard.js +17 -14
  72. package/dist/Components/KanbanBoard/KanbanBoard.js +93 -78
  73. package/dist/Components/LazyWrapper/LazyWrapper.d.ts +10 -0
  74. package/dist/Components/LazyWrapper/LazyWrapper.js +50 -0
  75. package/dist/Components/MoreItems/MoreItems.d.ts +4 -0
  76. package/dist/Components/MoreItems/MoreItems.js +35 -0
  77. package/dist/Components/MoreItems/MoreItemsProps.d.ts +29 -0
  78. package/dist/Components/MoreItems/MoreItemsProps.js +2 -0
  79. package/dist/Components/NavigationBar/NavigationBar.js +4 -4
  80. package/dist/Components/OrgSwitcher/OrgSwitcher.d.ts +4 -0
  81. package/dist/Components/OrgSwitcher/OrgSwitcher.js +121 -0
  82. package/dist/Components/OrgSwitcher/OrgSwitcherProps.d.ts +41 -0
  83. package/dist/Components/OrgSwitcher/OrgSwitcherProps.js +25 -0
  84. package/dist/Components/OrganizationDetails/CreateOrgModal.d.ts +4 -0
  85. package/dist/Components/OrganizationDetails/CreateOrgModal.js +122 -0
  86. package/dist/Components/OrganizationDetails/DeleteOrgModal.d.ts +4 -0
  87. package/dist/Components/OrganizationDetails/DeleteOrgModal.js +29 -0
  88. package/dist/Components/OrganizationDetails/OrganizationDetails.d.ts +4 -0
  89. package/dist/Components/OrganizationDetails/OrganizationDetails.js +264 -0
  90. package/dist/Components/OrganizationDetails/OrganizationDetails.test.d.ts +1 -0
  91. package/dist/Components/OrganizationDetails/OrganizationDetails.test.js +122 -0
  92. package/dist/Components/OrganizationDetails/OrganizationDetailsProps.d.ts +88 -0
  93. package/dist/Components/OrganizationDetails/OrganizationDetailsProps.js +2 -0
  94. package/dist/Components/PdfViewer/PdfViewer.d.ts +15 -0
  95. package/dist/Components/PdfViewer/PdfViewer.js +29 -0
  96. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.d.ts +1 -1
  97. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +42 -24
  98. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewerProps.d.ts +2 -0
  99. package/dist/Components/RolesPermission/DeleteRoleModal.d.ts +4 -0
  100. package/dist/Components/RolesPermission/DeleteRoleModal.js +29 -0
  101. package/dist/Components/RolesPermission/RolesPermission.d.ts +4 -0
  102. package/dist/Components/RolesPermission/RolesPermission.js +243 -0
  103. package/dist/Components/RolesPermission/RolesPermission.test.d.ts +1 -0
  104. package/dist/Components/RolesPermission/RolesPermission.test.js +150 -0
  105. package/dist/Components/RolesPermission/RolesPermissionProps.d.ts +117 -0
  106. package/dist/Components/RolesPermission/RolesPermissionProps.js +2 -0
  107. package/dist/Components/ScrollToTop/ScrollToTop.d.ts +19 -0
  108. package/dist/Components/ScrollToTop/ScrollToTop.js +104 -0
  109. package/dist/Components/SearchSelect/SearchSelect.js +53 -21
  110. package/dist/Components/SideBar/components/OtherApps.test.js +3 -2
  111. package/dist/Components/SignInActivityTable/SignInActivityTable.d.ts +4 -0
  112. package/dist/Components/SignInActivityTable/SignInActivityTable.js +95 -0
  113. package/dist/Components/SignInActivityTable/SignInActivityTable.test.d.ts +1 -0
  114. package/dist/Components/SignInActivityTable/SignInActivityTable.test.js +63 -0
  115. package/dist/Components/SignInActivityTable/SignInActivityTableProps.d.ts +21 -0
  116. package/dist/Components/SignInActivityTable/SignInActivityTableProps.js +2 -0
  117. package/dist/Components/StageProgress/StageItem.d.ts +4 -0
  118. package/dist/Components/StageProgress/StageItem.js +137 -0
  119. package/dist/Components/StageProgress/StageProgress.d.ts +4 -0
  120. package/dist/Components/StageProgress/StageProgress.js +59 -0
  121. package/dist/Components/StageProgress/StageProgressProps.d.ts +85 -0
  122. package/dist/Components/StageProgress/StageProgressProps.js +27 -0
  123. package/dist/Components/StageProgress/StepperStage.d.ts +4 -0
  124. package/dist/Components/StageProgress/StepperStage.js +78 -0
  125. package/dist/Components/Table/Table.d.ts +1 -1
  126. package/dist/Components/Table/Table.js +167 -32
  127. package/dist/Components/Table/TableProps.d.ts +11 -3
  128. package/dist/Components/Table/components/Pagination.js +1 -1
  129. package/dist/Components/Table/components/TableActions.d.ts +2 -2
  130. package/dist/Components/Table/components/TableActions.js +5 -4
  131. package/dist/Components/Table/components/TableBody.js +98 -29
  132. package/dist/Components/Table/components/TableBody.virtualize.test.js +13 -3
  133. package/dist/Components/Table/components/TableHeader.d.ts +1 -1
  134. package/dist/Components/Table/components/TableHeader.js +9 -13
  135. package/dist/Components/Table/hooks/useTable.d.ts +2 -1
  136. package/dist/Components/Table/hooks/useTable.js +24 -10
  137. package/dist/Components/Table/settings/ManageColumns.test.js +1 -0
  138. package/dist/Components/Table/settings/TableSettings.d.ts +3 -2
  139. package/dist/Components/Table/settings/TableSettings.js +30 -6
  140. package/dist/Components/Timeline/Timeline.d.ts +1 -1
  141. package/dist/Components/Timeline/Timeline.js +145 -78
  142. package/dist/Components/Toaster/Toaster.js +40 -20
  143. package/dist/Components/UpgradeButton/UpgradeButton.d.ts +4 -0
  144. package/dist/Components/UpgradeButton/UpgradeButton.js +73 -0
  145. package/dist/Components/UpgradeButton/UpgradeButtonProps.d.ts +43 -0
  146. package/dist/Components/UpgradeButton/UpgradeButtonProps.js +2 -0
  147. package/dist/Components/UserDetails/AddUserModal.d.ts +4 -0
  148. package/dist/Components/UserDetails/AddUserModal.js +218 -0
  149. package/dist/Components/UserDetails/ChangeRoleModal.d.ts +4 -0
  150. package/dist/Components/UserDetails/ChangeRoleModal.js +150 -0
  151. package/dist/Components/UserDetails/DeactivateConfirmModal.d.ts +4 -0
  152. package/dist/Components/UserDetails/DeactivateConfirmModal.js +34 -0
  153. package/dist/Components/UserDetails/UserDetails.d.ts +4 -0
  154. package/dist/Components/UserDetails/UserDetails.js +263 -0
  155. package/dist/Components/UserDetails/UserDetails.test.d.ts +1 -0
  156. package/dist/Components/UserDetails/UserDetails.test.js +129 -0
  157. package/dist/Components/UserDetails/UserDetailsProps.d.ts +151 -0
  158. package/dist/Components/UserDetails/UserDetailsProps.js +2 -0
  159. package/dist/Theme/index.d.ts +4 -4
  160. package/dist/Theme/index.js +4 -4
  161. package/dist/Utils/table.d.ts +6 -1
  162. package/dist/Utils/table.js +47 -27
  163. package/dist/index.d.ts +23 -1
  164. package/dist/index.js +37 -2
  165. package/package.json +1 -1
@@ -0,0 +1,117 @@
1
+ import { ReactNode } from "react";
2
+ export type PermissionKey = "read" | "create" | "edit" | "delete" | "import" | "export" | "automation";
3
+ export type Permission = {
4
+ module: string;
5
+ read: boolean;
6
+ create: boolean;
7
+ edit: boolean;
8
+ delete: boolean;
9
+ import?: boolean;
10
+ export?: boolean;
11
+ automation?: boolean;
12
+ };
13
+ export type RoleData = {
14
+ roleName: string;
15
+ createdBy: string;
16
+ created_at: string;
17
+ permission: Permission[];
18
+ roles_id: string;
19
+ designation: string;
20
+ makeSuperAdmin?: boolean;
21
+ automation?: boolean;
22
+ trackLocation?: boolean;
23
+ show_records?: boolean;
24
+ };
25
+ export type RolesPermissionView = "list" | "form";
26
+ export type RolesPermissionMode = "create" | "edit" | "view";
27
+ /**
28
+ * All user-facing strings. Provide translated values from the host app; every
29
+ * key has a sensible English default so the component works standalone.
30
+ */
31
+ export type RolesPermissionLabels = {
32
+ title?: string;
33
+ totalRoles?: string;
34
+ newRole?: string;
35
+ sNo?: string;
36
+ roleNameColumn?: string;
37
+ createdBy?: string;
38
+ createdTime?: string;
39
+ actions?: string;
40
+ noRoles?: string;
41
+ view?: string;
42
+ edit?: string;
43
+ delete?: string;
44
+ roleInformation?: string;
45
+ roleName?: string;
46
+ roleNamePlaceholder?: string;
47
+ enableAllPermissions?: string;
48
+ trackLocation?: string;
49
+ showAllUserRecords?: string;
50
+ permissionSettings?: string;
51
+ moduleName?: string;
52
+ read?: string;
53
+ create?: string;
54
+ editPermission?: string;
55
+ deletePermission?: string;
56
+ importPermission?: string;
57
+ exportPermission?: string;
58
+ noPermissions?: string;
59
+ cancel?: string;
60
+ saveChanges?: string;
61
+ updateChanges?: string;
62
+ readOnly?: string;
63
+ deleteRole?: string;
64
+ deleteRoleConfirm?: string;
65
+ };
66
+ export interface RolesPermissionProps {
67
+ /** Which view to render. */
68
+ view: RolesPermissionView;
69
+ /** Form mode (controls read-only vs editable form). */
70
+ mode?: RolesPermissionMode;
71
+ /** Roles list data. */
72
+ roles: RoleData[];
73
+ isRolesLoading?: boolean;
74
+ /** Permission matrix rows for the form view. */
75
+ permissions: Permission[];
76
+ /** Columns rendered in the matrix. Defaults to all non-automation keys. */
77
+ permissionKeys?: PermissionKey[];
78
+ /** Form field values (controlled). */
79
+ roleName: string;
80
+ roleNameError?: string;
81
+ isSuperAdmin: boolean;
82
+ isTrackLocation: boolean;
83
+ isShowRecords: boolean;
84
+ /** Whether the role is being edited (changes the Save button label). */
85
+ isEditing?: boolean;
86
+ /** Save in-flight flag. */
87
+ isSaving?: boolean;
88
+ /** List actions. */
89
+ onNewRole?: () => void;
90
+ onViewRole?: (role: RoleData) => void;
91
+ onEditRole?: (role: RoleData) => void;
92
+ onDeleteRole?: (roleId: number) => void;
93
+ onBack?: () => void;
94
+ /** Form actions. */
95
+ onRoleNameChange?: (value: string) => void;
96
+ onToggleSuperAdmin?: (checked: boolean) => void;
97
+ onToggleTrackLocation?: (checked: boolean) => void;
98
+ onToggleShowRecords?: (checked: boolean) => void;
99
+ onPermissionChange?: (module: string, key: PermissionKey) => void;
100
+ onSave?: () => void;
101
+ onCancelForm?: () => void;
102
+ /** App-specific sections rendered under the roles list (e.g. ModuleDelete, SignInActivity). */
103
+ footerSlot?: ReactNode;
104
+ /** Icon shown in the matrix for granted permissions in view mode. */
105
+ checkIcon?: ReactNode;
106
+ /** Translated/override strings. */
107
+ labels?: RolesPermissionLabels;
108
+ /** Outer padding override. Defaults to a compact value. */
109
+ padding?: string;
110
+ }
111
+ export interface DeleteRoleModalProps {
112
+ isOpen: boolean;
113
+ onClose: () => void;
114
+ onConfirm: () => void;
115
+ isLoading?: boolean;
116
+ labels: Required<Pick<RolesPermissionLabels, "deleteRole" | "deleteRoleConfirm" | "cancel" | "delete">>;
117
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ export interface ScrollToTopProps {
3
+ /** Content to wrap. The button watches the nearest scrollable ancestor. */
4
+ children: React.ReactNode;
5
+ /** Tooltip label on the button. */
6
+ tooltipLabel?: string;
7
+ /** Scroll distance (px) after which the button appears. */
8
+ threshold?: number;
9
+ /** Smooth-scroll duration in ms. */
10
+ duration?: number;
11
+ /** Pin to a window-level scroll instead of the wrapped parent. */
12
+ useWindow?: boolean;
13
+ /** Distance from the bottom edge. */
14
+ bottom?: string;
15
+ /** Distance from the right edge. */
16
+ right?: string;
17
+ }
18
+ declare const ScrollToTop: React.FC<ScrollToTopProps>;
19
+ export default ScrollToTop;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var react_1 = __importStar(require("react"));
40
+ var react_2 = require("@chakra-ui/react");
41
+ var lucide_react_1 = require("lucide-react");
42
+ var useCustomTheme_1 = require("../../Theme/useCustomTheme");
43
+ var ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
44
+ var ScrollToTop = function (_a) {
45
+ var _b;
46
+ var children = _a.children, _c = _a.tooltipLabel, tooltipLabel = _c === void 0 ? "Scroll to top" : _c, _d = _a.threshold, threshold = _d === void 0 ? 300 : _d, _e = _a.duration, duration = _e === void 0 ? 600 : _e, _f = _a.useWindow, useWindow = _f === void 0 ? false : _f, _g = _a.bottom, bottom = _g === void 0 ? "2rem" : _g, _h = _a.right, right = _h === void 0 ? "2rem" : _h;
47
+ var _j = (0, react_1.useState)(false), visible = _j[0], setVisible = _j[1];
48
+ var anchorRef = (0, react_1.useRef)(null);
49
+ var theme = (0, useCustomTheme_1.useCustomTheme)();
50
+ var getScroller = function () {
51
+ var _a, _b;
52
+ if (useWindow)
53
+ return window;
54
+ return (_b = (_a = anchorRef.current) === null || _a === void 0 ? void 0 : _a.parentElement) !== null && _b !== void 0 ? _b : null;
55
+ };
56
+ var handleScroll = function () {
57
+ var _a;
58
+ var scroller = getScroller();
59
+ var top = scroller === window
60
+ ? window.scrollY
61
+ : (_a = scroller === null || scroller === void 0 ? void 0 : scroller.scrollTop) !== null && _a !== void 0 ? _a : 0;
62
+ setVisible(top >= threshold);
63
+ };
64
+ var scrollToTop = function () {
65
+ var scroller = getScroller();
66
+ if (!scroller)
67
+ return;
68
+ var start = scroller === window ? window.scrollY : scroller.scrollTop;
69
+ var startTime = performance.now();
70
+ var step = function (now) {
71
+ var progress = Math.min((now - startTime) / duration, 1);
72
+ var eased = progress < 0.5
73
+ ? 2 * progress * progress
74
+ : -1 + (4 - 2 * progress) * progress;
75
+ var next = start * (1 - eased);
76
+ if (scroller === window)
77
+ window.scrollTo(0, next);
78
+ else
79
+ scroller.scrollTop = next;
80
+ if (progress < 1)
81
+ requestAnimationFrame(step);
82
+ };
83
+ requestAnimationFrame(step);
84
+ };
85
+ (0, react_1.useEffect)(function () {
86
+ var scroller = getScroller();
87
+ if (!scroller)
88
+ return;
89
+ scroller.addEventListener("scroll", handleScroll);
90
+ handleScroll();
91
+ return function () { return scroller.removeEventListener("scroll", handleScroll); };
92
+ // eslint-disable-next-line react-hooks/exhaustive-deps
93
+ }, [useWindow, threshold]);
94
+ return (react_1.default.createElement(react_2.Box, { ref: anchorRef, position: "relative" },
95
+ children,
96
+ react_1.default.createElement(ToolTip_1.default, { label: tooltipLabel, placement: "left" },
97
+ react_1.default.createElement(react_2.Box, { onClick: scrollToTop, role: "button", "aria-label": tooltipLabel, position: "fixed", bottom: bottom, right: right, zIndex: 1000, display: "flex", alignItems: "center", justifyContent: "center", boxSize: "44px", borderRadius: "full", cursor: "pointer", bg: theme.colors.primary[500], color: theme.colors.white, boxShadow: "0 4px 14px rgba(0,0,0,0.25)", opacity: visible ? 1 : 0, transform: visible ? "translateY(0) scale(1)" : "translateY(16px) scale(0.85)", pointerEvents: visible ? "auto" : "none", transition: "all 0.25s cubic-bezier(0.16, 1, 0.3, 1)", _hover: {
98
+ bg: (_b = theme.colors.primary[600]) !== null && _b !== void 0 ? _b : theme.colors.primary[500],
99
+ transform: "translateY(-2px) scale(1.05)",
100
+ boxShadow: "0 6px 20px rgba(0,0,0,0.3)",
101
+ }, _active: { transform: "scale(0.95)" } },
102
+ react_1.default.createElement(lucide_react_1.ChevronUp, { size: 24, strokeWidth: 2.5 })))));
103
+ };
104
+ exports.default = ScrollToTop;
@@ -90,19 +90,26 @@ var SearchSelect = function (_a) {
90
90
  var _y = (0, react_1.useState)(true), hasMore = _y[0], setHasMore = _y[1];
91
91
  var inputRef = (0, react_1.useRef)(null);
92
92
  var containerRef = (0, react_1.useRef)(null);
93
+ var controlRef = (0, react_1.useRef)(null);
94
+ var _z = (0, react_1.useState)({ top: 0, left: 0, width: 0 }), dropdownPos = _z[0], setDropdownPos = _z[1];
93
95
  var scrollTimeoutRef = (0, react_1.useRef)(null);
94
- var _z = (0, react_1.useState)(false), focused = _z[0], setFocused = _z[1];
95
- var _0 = (0, react_1.useState)(false), customSelectOpen = _0[0], setCustomSelectOpen = _0[1];
96
+ var _0 = (0, react_1.useState)(false), focused = _0[0], setFocused = _0[1];
97
+ var _1 = (0, react_1.useState)(false), customSelectOpen = _1[0], setCustomSelectOpen = _1[1];
96
98
  var customSelectRef = (0, react_1.useRef)(null);
97
- var _1 = (0, react_1.useState)({
99
+ var _2 = (0, react_1.useState)({
98
100
  top: 0,
99
101
  left: 0,
100
102
  width: 0,
101
- }), customSelectPos = _1[0], setCustomSelectPos = _1[1];
103
+ }), customSelectPos = _2[0], setCustomSelectPos = _2[1];
102
104
  var theme = (0, useCustomTheme_1.useCustomTheme)();
103
105
  (0, react_2.useOutsideClick)({
104
106
  ref: containerRef,
105
- handler: function () {
107
+ handler: function (e) {
108
+ // The options dropdown is portaled to <body>, so a click on it is "outside"
109
+ // the container — ignore those so selecting an option doesn't close first.
110
+ var dropdown = document.getElementById("searchselect-dropdown-portal");
111
+ if (dropdown && dropdown.contains(e.target))
112
+ return;
106
113
  setIsOpen(false);
107
114
  },
108
115
  });
@@ -223,10 +230,34 @@ var SearchSelect = function (_a) {
223
230
  });
224
231
  }
225
232
  }, [customSelectOpen]);
233
+ // Keep the portaled options dropdown anchored to the control (on open + while
234
+ // open if the page/modal scrolls or resizes).
235
+ var updateDropdownPos = (0, react_1.useCallback)(function () {
236
+ if (!controlRef.current)
237
+ return;
238
+ var rect = controlRef.current.getBoundingClientRect();
239
+ setDropdownPos({
240
+ top: rect.bottom + window.scrollY,
241
+ left: rect.left + window.scrollX,
242
+ width: rect.width,
243
+ });
244
+ }, []);
245
+ (0, react_1.useEffect)(function () {
246
+ if (!isOpen)
247
+ return;
248
+ updateDropdownPos();
249
+ // `true` (capture) catches scrolling inside any ancestor (e.g. modal body).
250
+ window.addEventListener("scroll", updateDropdownPos, true);
251
+ window.addEventListener("resize", updateDropdownPos);
252
+ return function () {
253
+ window.removeEventListener("scroll", updateDropdownPos, true);
254
+ window.removeEventListener("resize", updateDropdownPos);
255
+ };
256
+ }, [isOpen, updateDropdownPos]);
226
257
  return (react_1.default.createElement(react_2.Box, { ref: containerRef, width: width, position: "relative" },
227
258
  label && (react_1.default.createElement(FormLabel_1.TextLabel, { label: label, id: id, isRequired: isRequired, isInformation: isInformation !== null && isInformation !== void 0 ? isInformation : information === null || information === void 0 ? void 0 : information.isInformation, informationMessage: informationMessage !== null && informationMessage !== void 0 ? informationMessage : information === null || information === void 0 ? void 0 : information.informationMessage })),
228
259
  react_1.default.createElement(react_2.InputGroup, { size: size },
229
- react_1.default.createElement(react_2.Box, { as: "div", w: "100%", minH: s.minH, px: s.px, pr: s.pr, position: "relative", display: "flex", alignItems: "center", flexWrap: "wrap", gap: s.gap, border: "0.063rem solid", borderColor: error
260
+ react_1.default.createElement(react_2.Box, { as: "div", ref: controlRef, w: "100%", minH: s.minH, px: s.px, pr: s.pr, position: "relative", display: "flex", alignItems: "center", flexWrap: "wrap", gap: s.gap, border: "0.063rem solid", borderColor: error
230
261
  ? theme.colors.semantic.error[500]
231
262
  : focused
232
263
  ? theme.colors.primary[500]
@@ -275,22 +306,23 @@ var SearchSelect = function (_a) {
275
306
  e.stopPropagation();
276
307
  setIsOpen(function (prev) { return !prev; });
277
308
  }, "aria-label": "toggle-dropdown", display: "flex", alignItems: "center" }, isOpen ? (react_1.default.createElement(lucide_react_1.ChevronUp, { size: s.chevronSize })) : (react_1.default.createElement(lucide_react_1.ChevronDown, { size: s.chevronSize }))))))),
278
- isOpen && (react_1.default.createElement(react_2.Box, { position: "absolute", zIndex: 10, width: "100%", maxH: "20rem", borderWidth: 1, borderRadius: "sm", bg: theme.colors.white, boxShadow: "md", display: "flex", flexDirection: "column" },
279
- isMultiple && isSelectAll && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
280
- react_1.default.createElement(Checkbox_1.default, { isChecked: allFilteredSelected, sx: { pointerEvents: "none" }, size: s.checkboxSize }),
281
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, allFilteredSelected ? "Unselect All" : "Select All"))),
282
- react_1.default.createElement(react_2.Box, { flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: "0.063rem solid", borderColor: theme.colors.gray[200] }, isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH },
283
- react_1.default.createElement(react_2.Spinner, { size: s.spinnerSize }),
284
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText))) : !isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Text, { p: 3, fontSize: s.dropdownTextFontSize, color: theme.colors.gray[500] }, "No results found")) : (react_1.default.createElement(react_1.default.Fragment, null,
285
- filteredOptions.map(function (option) { return (react_1.default.createElement(react_2.Box, { key: option.id, py: s.optionRowPy, px: 3, minH: s.optionRowMinH, cursor: "pointer", bg: isSelected(option.id) ? theme.colors.gray[100] : "transparent", _hover: { bg: theme.colors.gray[50] }, onClick: function () { return handleSelect(option); }, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
286
- isMultiple && (react_1.default.createElement(Checkbox_1.default, { isChecked: isSelected(option.id), sx: { pointerEvents: "none" }, size: s.checkboxSize })),
287
- option.view ? (react_1.default.createElement(react_1.default.Fragment, null, option.view)) : (react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, option.label)))); }),
288
- ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", justifyContent: "center", gap: 2, minH: s.optionRowMinH },
309
+ isOpen && (react_1.default.createElement(react_2.Portal, null,
310
+ react_1.default.createElement(react_2.Box, { id: "searchselect-dropdown-portal", position: "absolute", top: "".concat(dropdownPos.top, "px"), left: "".concat(dropdownPos.left, "px"), width: "".concat(dropdownPos.width, "px"), zIndex: 1500, maxH: "20rem", borderWidth: 1, borderColor: theme.colors.gray[200], borderRadius: "sm", bg: theme.colors.white, boxShadow: "md", display: "flex", flexDirection: "column" },
311
+ isMultiple && isSelectAll && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, cursor: "pointer", onClick: handleSelectAll, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
312
+ react_1.default.createElement(Checkbox_1.default, { isChecked: allFilteredSelected, sx: { pointerEvents: "none" }, size: s.checkboxSize }),
313
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, allFilteredSelected ? "Unselect All" : "Select All"))),
314
+ react_1.default.createElement(react_2.Box, { flex: "1", overflowY: "auto", onScroll: handleScroll, maxH: "15rem", borderBottom: "0.063rem solid", borderColor: theme.colors.gray[200] }, isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH },
289
315
  react_1.default.createElement(react_2.Spinner, { size: s.spinnerSize }),
290
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText)))))),
291
- (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, borderTop: "0.063rem solid", borderColor: theme.colors.gray[200], bg: theme.colors.white, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: theme.colors.gray[50] } },
292
- addNew.icon || react_1.default.createElement(lucide_react_1.Plus, { size: s.addNewIconSize }),
293
- react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, addNew.text || "Add New"))))),
316
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText))) : !isOptionLoading && filteredOptions.length === 0 ? (react_1.default.createElement(react_2.Text, { p: 3, fontSize: s.dropdownTextFontSize, color: theme.colors.gray[500] }, "No results found")) : (react_1.default.createElement(react_1.default.Fragment, null,
317
+ filteredOptions.map(function (option) { return (react_1.default.createElement(react_2.Box, { key: option.id, py: s.optionRowPy, px: 3, minH: s.optionRowMinH, cursor: "pointer", bg: isSelected(option.id) ? theme.colors.gray[100] : "transparent", _hover: { bg: theme.colors.gray[50] }, onClick: function () { return handleSelect(option); }, display: "flex", alignItems: "center", gap: 2, borderBottom: "0.063rem solid ".concat(theme.colors.gray[100]) },
318
+ isMultiple && (react_1.default.createElement(Checkbox_1.default, { isChecked: isSelected(option.id), sx: { pointerEvents: "none" }, size: s.checkboxSize })),
319
+ option.view ? (react_1.default.createElement(react_1.default.Fragment, null, option.view)) : (react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, option.label)))); }),
320
+ ((pagination === null || pagination === void 0 ? void 0 : pagination.scrollLoading) || (isOptionLoading && filteredOptions.length > 0)) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, display: "flex", alignItems: "center", justifyContent: "center", gap: 2, minH: s.optionRowMinH },
321
+ react_1.default.createElement(react_2.Spinner, { size: s.spinnerSize }),
322
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, loadingText)))))),
323
+ (addNew === null || addNew === void 0 ? void 0 : addNew.enabled) && (react_1.default.createElement(react_2.Box, { py: s.optionRowPy, px: 3, borderTop: "0.063rem solid", borderColor: theme.colors.gray[200], bg: theme.colors.white, display: "flex", alignItems: "center", gap: 2, minH: s.optionRowMinH, cursor: "pointer", onClick: addNew.onClick, _hover: { bg: theme.colors.gray[50] } },
324
+ addNew.icon || react_1.default.createElement(lucide_react_1.Plus, { size: s.addNewIconSize }),
325
+ react_1.default.createElement(react_2.Text, { fontSize: s.dropdownTextFontSize }, addNew.text || "Add New")))))),
294
326
  helperText && !error && react_1.default.createElement(HelperText_1.default, { helperText: helperText }),
295
327
  error && react_1.default.createElement(ErrorMessage_1.default, { errorMessage: errorMessage })));
296
328
  };
@@ -78,10 +78,11 @@ describe("OtherApps", function () {
78
78
  beforeEach(function () {
79
79
  jest.clearAllMocks();
80
80
  });
81
- it("does not render flyout copy when expanded", function () {
81
+ it("renders the section header and inline labels when expanded", function () {
82
82
  renderWithChakra(react_1.default.createElement(OtherApps_1.default, { toggle: false, otherApps: sampleApps }));
83
- expect(react_2.screen.getByText("Other Apps")).toBeInTheDocument();
83
+ expect(react_2.screen.getByText("Switch app")).toBeInTheDocument();
84
84
  expect(react_2.screen.getByText("Billing")).toBeInTheDocument();
85
+ expect(react_2.screen.getByText("Tickets")).toBeInTheDocument();
85
86
  expect(react_2.screen.queryAllByRole("tooltip")).toHaveLength(0);
86
87
  });
87
88
  it("shows flyout with Open label on hover when collapsed", function () { return __awaiter(void 0, void 0, void 0, function () {
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { SignInActivityTableProps } from "./SignInActivityTableProps";
3
+ declare const SignInActivityTable: React.FC<SignInActivityTableProps>;
4
+ export default SignInActivityTable;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ var __importDefault = (this && this.__importDefault) || function (mod) {
47
+ return (mod && mod.__esModule) ? mod : { "default": mod };
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ var react_1 = __importStar(require("react"));
51
+ var react_2 = require("@chakra-ui/react");
52
+ var lucide_react_1 = require("lucide-react");
53
+ var useCustomTheme_1 = require("../../Theme/useCustomTheme");
54
+ var EmptyState_1 = __importDefault(require("../EmptyState/EmptyState"));
55
+ var DEFAULT_LABELS = {
56
+ title: "Recent Sign-in Devices",
57
+ browser: "Browser",
58
+ device: "Device",
59
+ recentActivity: "Recent Activity",
60
+ noActivity: "No recent sign-in activity",
61
+ };
62
+ var SignInActivityTable = function (_a) {
63
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
64
+ var devices = _a.devices, _o = _a.isLoading, isLoading = _o === void 0 ? false : _o, labelOverrides = _a.labels;
65
+ var colors = (0, useCustomTheme_1.useCustomTheme)().colors;
66
+ var labels = (0, react_1.useMemo)(function () { return (__assign(__assign({}, DEFAULT_LABELS), labelOverrides)); }, [labelOverrides]);
67
+ var border = (_e = (_c = (_b = colors === null || colors === void 0 ? void 0 : colors.boxborder) === null || _b === void 0 ? void 0 : _b[200]) !== null && _c !== void 0 ? _c : (_d = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _d === void 0 ? void 0 : _d[200]) !== null && _e !== void 0 ? _e : "#E2E8F0";
68
+ var surface = (_f = colors === null || colors === void 0 ? void 0 : colors.white) !== null && _f !== void 0 ? _f : "#FFFFFF";
69
+ var muted = (_h = (_g = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _g === void 0 ? void 0 : _g[500]) !== null && _h !== void 0 ? _h : "#64748B";
70
+ var heading = (_k = (_j = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _j === void 0 ? void 0 : _j[800]) !== null && _k !== void 0 ? _k : "#1E293B";
71
+ var headBg = (_m = (_l = colors === null || colors === void 0 ? void 0 : colors.gray) === null || _l === void 0 ? void 0 : _l[50]) !== null && _m !== void 0 ? _m : "#F8FAFC";
72
+ var thStyle = {
73
+ fontSize: "0.7rem",
74
+ textTransform: "uppercase",
75
+ letterSpacing: "0.04em",
76
+ color: muted,
77
+ borderColor: border,
78
+ py: 3,
79
+ };
80
+ return (react_1.default.createElement(react_2.Box, { mt: 4, backgroundColor: surface, borderRadius: "xl", border: "1px solid", borderColor: border, boxShadow: "0 1px 2px rgba(16,24,40,0.05)", overflow: "hidden" },
81
+ react_1.default.createElement(react_2.Flex, { px: 4, py: 3, borderBottom: "1px solid", borderColor: border, alignItems: "center" },
82
+ react_1.default.createElement(react_2.Heading, { size: "sm", fontWeight: 600, color: heading }, labels.title)),
83
+ react_1.default.createElement(react_2.Box, { overflowX: "auto" }, isLoading ? (react_1.default.createElement(react_2.VStack, { spacing: 3, p: 4, align: "stretch" }, Array.from({ length: 4 }).map(function (_, idx) { return (react_1.default.createElement(react_2.Skeleton, { key: idx, height: "18px", borderRadius: "md" })); }))) : devices.length === 0 ? (react_1.default.createElement(EmptyState_1.default, { icon: lucide_react_1.MonitorSmartphone, title: labels.noActivity, size: "sm", minH: "160px" })) : (react_1.default.createElement(react_2.Table, { variant: "simple", size: "sm" },
84
+ react_1.default.createElement(react_2.Thead, { bg: headBg },
85
+ react_1.default.createElement(react_2.Tr, null,
86
+ react_1.default.createElement(react_2.Th, __assign({}, thStyle), labels.browser),
87
+ react_1.default.createElement(react_2.Th, __assign({}, thStyle), labels.device),
88
+ react_1.default.createElement(react_2.Th, __assign({}, thStyle), labels.recentActivity))),
89
+ react_1.default.createElement(react_2.Tbody, null, devices.map(function (device, index) { return (react_1.default.createElement(react_2.Tr, { key: index, _hover: { bg: headBg }, transition: "background 0.15s ease" },
90
+ react_1.default.createElement(react_2.Td, { borderColor: border, fontSize: "sm", fontWeight: 500, color: heading }, device.browser || "—"),
91
+ react_1.default.createElement(react_2.Td, { borderColor: border, fontSize: "sm", color: muted }, device.device),
92
+ react_1.default.createElement(react_2.Td, { borderColor: border, fontSize: "sm", color: muted },
93
+ react_1.default.createElement(react_2.Text, null, device.activity)))); })))))));
94
+ };
95
+ exports.default = SignInActivityTable;
@@ -0,0 +1 @@
1
+ import "@testing-library/jest-dom";
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ var react_1 = __importDefault(require("react"));
7
+ var react_2 = require("@testing-library/react");
8
+ require("@testing-library/jest-dom");
9
+ var react_3 = require("@chakra-ui/react");
10
+ var SignInActivityTable_1 = __importDefault(require("./SignInActivityTable"));
11
+ jest.mock("../../Theme/useCustomTheme", function () { return ({
12
+ useCustomTheme: function () { return ({
13
+ colors: {
14
+ white: "#ffffff",
15
+ gray: {
16
+ 50: "#f8fafc",
17
+ 100: "#f0f0f0",
18
+ 200: "#e2e8f0",
19
+ 500: "#64748b",
20
+ 600: "#475569",
21
+ 800: "#1e293b",
22
+ },
23
+ primary: { 50: "#eef2ff", 500: "#6366f1" },
24
+ boxborder: { 200: "#e2e8f0" },
25
+ },
26
+ }); },
27
+ }); });
28
+ beforeAll(function () {
29
+ Object.defineProperty(window, "matchMedia", {
30
+ writable: true,
31
+ configurable: true,
32
+ value: jest.fn().mockImplementation(function (query) { return ({
33
+ matches: false,
34
+ media: query,
35
+ onchange: null,
36
+ addListener: jest.fn(),
37
+ removeListener: jest.fn(),
38
+ addEventListener: jest.fn(),
39
+ removeEventListener: jest.fn(),
40
+ dispatchEvent: jest.fn(),
41
+ }); }),
42
+ });
43
+ });
44
+ var devices = [
45
+ { browser: "Chrome", device: "MacBook Pro", activity: "2 minutes ago" },
46
+ { browser: "Safari", device: "iPhone 15", activity: "Yesterday" },
47
+ ];
48
+ var renderWithChakra = function (ui) {
49
+ return (0, react_2.render)(react_1.default.createElement(react_3.ChakraProvider, null, ui));
50
+ };
51
+ describe("SignInActivityTable", function () {
52
+ it("renders the device rows", function () {
53
+ renderWithChakra(react_1.default.createElement(SignInActivityTable_1.default, { devices: devices }));
54
+ expect(react_2.screen.getByText("Recent Sign-in Devices")).toBeInTheDocument();
55
+ expect(react_2.screen.getByText("Chrome")).toBeInTheDocument();
56
+ expect(react_2.screen.getByText("MacBook Pro")).toBeInTheDocument();
57
+ expect(react_2.screen.getByText("2 minutes ago")).toBeInTheDocument();
58
+ });
59
+ it("shows an empty state when there is no activity", function () {
60
+ renderWithChakra(react_1.default.createElement(SignInActivityTable_1.default, { devices: [] }));
61
+ expect(react_2.screen.getByText("No recent sign-in activity")).toBeInTheDocument();
62
+ });
63
+ });
@@ -0,0 +1,21 @@
1
+ export type SignInDevice = {
2
+ browser: string;
3
+ device: string;
4
+ activity: string;
5
+ };
6
+ /**
7
+ * All user-facing strings. Provide translated values from the host app; every
8
+ * key has a sensible English default so the component works standalone.
9
+ */
10
+ export type SignInActivityLabels = {
11
+ title?: string;
12
+ browser?: string;
13
+ device?: string;
14
+ recentActivity?: string;
15
+ noActivity?: string;
16
+ };
17
+ export interface SignInActivityTableProps {
18
+ devices: SignInDevice[];
19
+ isLoading?: boolean;
20
+ labels?: SignInActivityLabels;
21
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { StageItemProps } from "./StageProgressProps";
3
+ declare const StageItem: React.FC<StageItemProps>;
4
+ export default StageItem;