@oneuptime/common 9.3.22 → 9.4.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.
Files changed (121) hide show
  1. package/Models/DatabaseModels/IncomingCallLog.ts +521 -0
  2. package/Models/DatabaseModels/IncomingCallLogItem.ts +463 -0
  3. package/Models/DatabaseModels/IncomingCallPolicy.ts +811 -0
  4. package/Models/DatabaseModels/IncomingCallPolicyEscalationRule.ts +597 -0
  5. package/Models/DatabaseModels/Index.ts +18 -0
  6. package/Models/DatabaseModels/ProjectSCIMLog.ts +422 -0
  7. package/Models/DatabaseModels/StatusPageSCIMLog.ts +455 -0
  8. package/Models/DatabaseModels/User.ts +0 -15
  9. package/Models/DatabaseModels/UserIncomingCallNumber.ts +296 -0
  10. package/Server/API/UserIncomingCallNumberAPI.ts +128 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.ts +121 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.ts +22 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.ts +787 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.ts +29 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  16. package/Server/Services/IncomingCallLogItemService.ts +10 -0
  17. package/Server/Services/IncomingCallLogService.ts +10 -0
  18. package/Server/Services/IncomingCallPolicyEscalationRuleService.ts +267 -0
  19. package/Server/Services/IncomingCallPolicyService.ts +10 -0
  20. package/Server/Services/Index.ts +7 -0
  21. package/Server/Services/ProjectSCIMLogService.ts +11 -0
  22. package/Server/Services/StatusPageSCIMLogService.ts +11 -0
  23. package/Server/Services/UserCallService.ts +31 -0
  24. package/Server/Services/UserIncomingCallNumberService.ts +258 -0
  25. package/Server/Services/UserSmsService.ts +31 -0
  26. package/Server/Utils/StartServer.ts +5 -0
  27. package/Types/Call/CallProvider.ts +99 -0
  28. package/Types/Call/CallProviderType.ts +6 -0
  29. package/Types/Icon/IconProp.ts +1 -0
  30. package/Types/IncomingCall/IncomingCallStatus.ts +13 -0
  31. package/Types/Permission.ts +126 -0
  32. package/Types/Phone.ts +53 -4
  33. package/Types/SCIM/SCIMLogStatus.ts +7 -0
  34. package/UI/Components/Diagram/ConceptCards.tsx +74 -0
  35. package/UI/Components/Diagram/HorizontalStepChain.tsx +92 -0
  36. package/UI/Components/Diagram/Index.ts +11 -0
  37. package/UI/Components/Diagram/NumberedSteps.tsx +77 -0
  38. package/UI/Components/Diagram/VerticalFlowSteps.tsx +59 -0
  39. package/UI/Components/Icon/Icon.tsx +10 -0
  40. package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +86 -2
  41. package/build/dist/Models/DatabaseModels/IncomingCallLog.js +565 -0
  42. package/build/dist/Models/DatabaseModels/IncomingCallLog.js.map +1 -0
  43. package/build/dist/Models/DatabaseModels/IncomingCallLogItem.js +497 -0
  44. package/build/dist/Models/DatabaseModels/IncomingCallLogItem.js.map +1 -0
  45. package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +840 -0
  46. package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -0
  47. package/build/dist/Models/DatabaseModels/IncomingCallPolicyEscalationRule.js +619 -0
  48. package/build/dist/Models/DatabaseModels/IncomingCallPolicyEscalationRule.js.map +1 -0
  49. package/build/dist/Models/DatabaseModels/Index.js +16 -0
  50. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  51. package/build/dist/Models/DatabaseModels/ProjectSCIMLog.js +455 -0
  52. package/build/dist/Models/DatabaseModels/ProjectSCIMLog.js.map +1 -0
  53. package/build/dist/Models/DatabaseModels/StatusPageSCIMLog.js +486 -0
  54. package/build/dist/Models/DatabaseModels/StatusPageSCIMLog.js.map +1 -0
  55. package/build/dist/Models/DatabaseModels/User.js +0 -16
  56. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  57. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +315 -0
  58. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -0
  59. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +72 -0
  60. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -0
  61. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.js +48 -0
  62. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.js.map +1 -0
  63. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.js +34 -0
  64. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.js.map +1 -0
  65. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.js +270 -0
  66. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.js.map +1 -0
  67. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.js +16 -0
  68. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.js.map +1 -0
  69. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  70. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  71. package/build/dist/Server/Services/IncomingCallLogItemService.js +9 -0
  72. package/build/dist/Server/Services/IncomingCallLogItemService.js.map +1 -0
  73. package/build/dist/Server/Services/IncomingCallLogService.js +9 -0
  74. package/build/dist/Server/Services/IncomingCallLogService.js.map +1 -0
  75. package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js +197 -0
  76. package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js.map +1 -0
  77. package/build/dist/Server/Services/IncomingCallPolicyService.js +9 -0
  78. package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -0
  79. package/build/dist/Server/Services/Index.js +6 -0
  80. package/build/dist/Server/Services/Index.js.map +1 -1
  81. package/build/dist/Server/Services/ProjectSCIMLogService.js +10 -0
  82. package/build/dist/Server/Services/ProjectSCIMLogService.js.map +1 -0
  83. package/build/dist/Server/Services/StatusPageSCIMLogService.js +10 -0
  84. package/build/dist/Server/Services/StatusPageSCIMLogService.js.map +1 -0
  85. package/build/dist/Server/Services/UserCallService.js +21 -0
  86. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  87. package/build/dist/Server/Services/UserIncomingCallNumberService.js +225 -0
  88. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -0
  89. package/build/dist/Server/Services/UserSmsService.js +21 -0
  90. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  91. package/build/dist/Server/Utils/StartServer.js +5 -0
  92. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  93. package/build/dist/Types/Call/CallProvider.js +2 -0
  94. package/build/dist/Types/Call/CallProvider.js.map +1 -0
  95. package/build/dist/Types/Call/CallProviderType.js +7 -0
  96. package/build/dist/Types/Call/CallProviderType.js.map +1 -0
  97. package/build/dist/Types/Icon/IconProp.js +1 -0
  98. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  99. package/build/dist/Types/IncomingCall/IncomingCallStatus.js +14 -0
  100. package/build/dist/Types/IncomingCall/IncomingCallStatus.js.map +1 -0
  101. package/build/dist/Types/Permission.js +104 -0
  102. package/build/dist/Types/Permission.js.map +1 -1
  103. package/build/dist/Types/Phone.js +47 -3
  104. package/build/dist/Types/Phone.js.map +1 -1
  105. package/build/dist/Types/SCIM/SCIMLogStatus.js +8 -0
  106. package/build/dist/Types/SCIM/SCIMLogStatus.js.map +1 -0
  107. package/build/dist/UI/Components/Diagram/ConceptCards.js +30 -0
  108. package/build/dist/UI/Components/Diagram/ConceptCards.js.map +1 -0
  109. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +30 -0
  110. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -0
  111. package/build/dist/UI/Components/Diagram/Index.js +5 -0
  112. package/build/dist/UI/Components/Diagram/Index.js.map +1 -0
  113. package/build/dist/UI/Components/Diagram/NumberedSteps.js +18 -0
  114. package/build/dist/UI/Components/Diagram/NumberedSteps.js.map +1 -0
  115. package/build/dist/UI/Components/Diagram/VerticalFlowSteps.js +16 -0
  116. package/build/dist/UI/Components/Diagram/VerticalFlowSteps.js.map +1 -0
  117. package/build/dist/UI/Components/Icon/Icon.js +4 -0
  118. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  119. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +30 -1
  120. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
  121. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ import React, { FunctionComponent, ReactElement } from "react";
2
+ import Icon from "../Icon/Icon";
3
+ import IconProp from "../../../Types/Icon/IconProp";
4
+ import Color from "../../../Types/Color";
5
+
6
+ export interface ConceptCard {
7
+ title: string;
8
+ description: string;
9
+ icon: IconProp;
10
+ iconColor: Color;
11
+ }
12
+
13
+ export interface ComponentProps {
14
+ cards: ConceptCard[];
15
+ /** Number of columns in the grid (1-4). Default is 2. */
16
+ columns?: 1 | 2 | 3 | 4 | undefined;
17
+ }
18
+
19
+ const ConceptCards: FunctionComponent<ComponentProps> = (
20
+ props: ComponentProps,
21
+ ): ReactElement => {
22
+ const columns: number = props.columns || 2;
23
+
24
+ const getGridClasses: () => string = (): string => {
25
+ switch (columns) {
26
+ case 1:
27
+ return "grid-cols-1";
28
+ case 2:
29
+ return "grid-cols-1 md:grid-cols-2";
30
+ case 3:
31
+ return "grid-cols-1 md:grid-cols-2 lg:grid-cols-3";
32
+ case 4:
33
+ return "grid-cols-1 md:grid-cols-2 lg:grid-cols-4";
34
+ default:
35
+ return "grid-cols-1 md:grid-cols-2";
36
+ }
37
+ };
38
+
39
+ return (
40
+ <div className={`grid ${getGridClasses()} gap-3`}>
41
+ {props.cards.map((card: ConceptCard, index: number) => {
42
+ return (
43
+ <div
44
+ key={index}
45
+ className="border border-gray-200 rounded-md p-3 bg-white hover:border-gray-300 transition-colors"
46
+ >
47
+ <div className="flex items-start space-x-3">
48
+ <div
49
+ className="flex-shrink-0 w-8 h-8 rounded flex items-center justify-center"
50
+ style={{ backgroundColor: `${card.iconColor.toString()}15` }}
51
+ >
52
+ <Icon
53
+ icon={card.icon}
54
+ className="h-4 w-4"
55
+ style={{ color: card.iconColor.toString() }}
56
+ />
57
+ </div>
58
+ <div className="flex-1 min-w-0">
59
+ <h4 className="text-sm font-medium text-gray-900">
60
+ {card.title}
61
+ </h4>
62
+ <p className="text-sm text-gray-500 mt-1 leading-relaxed">
63
+ {card.description}
64
+ </p>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ );
69
+ })}
70
+ </div>
71
+ );
72
+ };
73
+
74
+ export default ConceptCards;
@@ -0,0 +1,92 @@
1
+ import React, { FunctionComponent, ReactElement } from "react";
2
+ import Icon from "../Icon/Icon";
3
+ import IconProp from "../../../Types/Icon/IconProp";
4
+ import Color from "../../../Types/Color";
5
+
6
+ export interface ChainStep {
7
+ stepNumber: number;
8
+ title: string;
9
+ description: string;
10
+ color: Color;
11
+ /** Optional label shown below the step number. Default is "Step" */
12
+ stepLabel?: string | undefined;
13
+ }
14
+
15
+ export interface ChainEndStep {
16
+ title: string;
17
+ description: string;
18
+ icon: IconProp;
19
+ color: Color;
20
+ }
21
+
22
+ export interface ComponentProps {
23
+ steps: ChainStep[];
24
+ endStep?: ChainEndStep | undefined;
25
+ /** Default label for steps. Default is "Step" */
26
+ defaultStepLabel?: string | undefined;
27
+ }
28
+
29
+ const HorizontalStepChain: FunctionComponent<ComponentProps> = (
30
+ props: ComponentProps,
31
+ ): ReactElement => {
32
+ const defaultLabel: string = props.defaultStepLabel || "Step";
33
+
34
+ return (
35
+ <div className="flex items-center flex-wrap gap-3">
36
+ {props.steps.map((step: ChainStep, index: number) => {
37
+ return (
38
+ <React.Fragment key={index}>
39
+ {/* Step */}
40
+ <div className="flex items-center space-x-3">
41
+ <div
42
+ className="w-10 h-10 rounded-full flex items-center justify-center text-white text-sm font-medium"
43
+ style={{ backgroundColor: step.color.toString() }}
44
+ >
45
+ {step.stepNumber}
46
+ </div>
47
+ <div>
48
+ <p className="text-sm font-medium text-gray-900">
49
+ {step.title}
50
+ </p>
51
+ <p className="text-xs text-gray-500">
52
+ {step.stepLabel || defaultLabel} {step.stepNumber} ·{" "}
53
+ {step.description}
54
+ </p>
55
+ </div>
56
+ </div>
57
+
58
+ {/* Arrow */}
59
+ <Icon
60
+ icon={IconProp.ChevronRight}
61
+ className="h-4 w-4 text-gray-300 hidden sm:block"
62
+ />
63
+ </React.Fragment>
64
+ );
65
+ })}
66
+
67
+ {/* End Step */}
68
+ {props.endStep && (
69
+ <div className="flex items-center space-x-3">
70
+ <div
71
+ className="w-10 h-10 rounded-full flex items-center justify-center"
72
+ style={{ backgroundColor: `${props.endStep.color.toString()}15` }}
73
+ >
74
+ <Icon
75
+ icon={props.endStep.icon}
76
+ className="h-4 w-4"
77
+ style={{ color: props.endStep.color.toString() }}
78
+ />
79
+ </div>
80
+ <div>
81
+ <p className="text-sm font-medium text-gray-900">
82
+ {props.endStep.title}
83
+ </p>
84
+ <p className="text-xs text-gray-500">{props.endStep.description}</p>
85
+ </div>
86
+ </div>
87
+ )}
88
+ </div>
89
+ );
90
+ };
91
+
92
+ export default HorizontalStepChain;
@@ -0,0 +1,11 @@
1
+ export { default as VerticalFlowSteps } from "./VerticalFlowSteps";
2
+ export type { FlowStep } from "./VerticalFlowSteps";
3
+
4
+ export { default as HorizontalStepChain } from "./HorizontalStepChain";
5
+ export type { ChainStep, ChainEndStep } from "./HorizontalStepChain";
6
+
7
+ export { default as NumberedSteps } from "./NumberedSteps";
8
+ export type { NumberedStep } from "./NumberedSteps";
9
+
10
+ export { default as ConceptCards } from "./ConceptCards";
11
+ export type { ConceptCard } from "./ConceptCards";
@@ -0,0 +1,77 @@
1
+ import React, { FunctionComponent, ReactElement } from "react";
2
+ import Icon from "../Icon/Icon";
3
+ import IconProp from "../../../Types/Icon/IconProp";
4
+ import Color from "../../../Types/Color";
5
+
6
+ export interface NumberedStep {
7
+ title: string;
8
+ description: string;
9
+ /** If provided, shows an icon instead of number */
10
+ icon?: IconProp | undefined;
11
+ /** Color for the step indicator */
12
+ color?: Color | undefined;
13
+ }
14
+
15
+ export interface ComponentProps {
16
+ steps: NumberedStep[];
17
+ /** Default color for steps */
18
+ defaultColor?: Color | undefined;
19
+ }
20
+
21
+ const NumberedSteps: FunctionComponent<ComponentProps> = (
22
+ props: ComponentProps,
23
+ ): ReactElement => {
24
+ const defaultColor: Color = props.defaultColor || new Color("#6b7280"); // gray-500
25
+
26
+ return (
27
+ <div className="relative">
28
+ {props.steps.map((step: NumberedStep, index: number) => {
29
+ const color: Color = step.color || defaultColor;
30
+ const isLast: boolean = index === props.steps.length - 1;
31
+
32
+ return (
33
+ <div key={index} className="relative flex items-start pb-5 last:pb-0">
34
+ {/* Vertical line connecting steps */}
35
+ {!isLast && (
36
+ <div
37
+ className="absolute left-4 top-10 w-px bg-gray-200"
38
+ style={{ height: "calc(100% - 1.5rem)" }}
39
+ />
40
+ )}
41
+
42
+ {/* Number/Icon indicator */}
43
+ <div
44
+ className="relative flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center border-2 bg-white"
45
+ style={{ borderColor: color.toString() }}
46
+ >
47
+ {step.icon ? (
48
+ <Icon
49
+ icon={step.icon}
50
+ className="h-4 w-4"
51
+ style={{ color: color.toString() }}
52
+ />
53
+ ) : (
54
+ <span
55
+ className="text-sm font-medium"
56
+ style={{ color: color.toString() }}
57
+ >
58
+ {index + 1}
59
+ </span>
60
+ )}
61
+ </div>
62
+
63
+ {/* Content */}
64
+ <div className="ml-4 flex-1 pt-0.5">
65
+ <h4 className="text-sm font-medium text-gray-900">
66
+ {step.title}
67
+ </h4>
68
+ <p className="text-sm text-gray-500 mt-0.5">{step.description}</p>
69
+ </div>
70
+ </div>
71
+ );
72
+ })}
73
+ </div>
74
+ );
75
+ };
76
+
77
+ export default NumberedSteps;
@@ -0,0 +1,59 @@
1
+ import React, { FunctionComponent, ReactElement } from "react";
2
+ import Icon from "../Icon/Icon";
3
+ import IconProp from "../../../Types/Icon/IconProp";
4
+ import Color from "../../../Types/Color";
5
+
6
+ export interface FlowStep {
7
+ title: string;
8
+ description: string;
9
+ icon: IconProp;
10
+ iconColor: Color;
11
+ }
12
+
13
+ export interface ComponentProps {
14
+ steps: FlowStep[];
15
+ }
16
+
17
+ const VerticalFlowSteps: FunctionComponent<ComponentProps> = (
18
+ props: ComponentProps,
19
+ ): ReactElement => {
20
+ return (
21
+ <div className="relative">
22
+ {props.steps.map((step: FlowStep, index: number) => {
23
+ const isLast: boolean = index === props.steps.length - 1;
24
+
25
+ return (
26
+ <div key={index} className="relative flex items-start pb-6 last:pb-0">
27
+ {/* Vertical line connecting steps */}
28
+ {!isLast && (
29
+ <div
30
+ className="absolute left-4 top-10 w-px bg-gray-200"
31
+ style={{ height: "calc(100% - 1rem)" }}
32
+ />
33
+ )}
34
+
35
+ {/* Icon */}
36
+ <div
37
+ className="relative flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center border border-gray-200 bg-white"
38
+ style={{ borderColor: `${step.iconColor.toString()}40` }}
39
+ >
40
+ <Icon
41
+ icon={step.icon}
42
+ className="h-4 w-4"
43
+ style={{ color: step.iconColor.toString() }}
44
+ />
45
+ </div>
46
+
47
+ {/* Content */}
48
+ <div className="ml-4 flex-1">
49
+ <p className="text-sm font-medium text-gray-900">{step.title}</p>
50
+ <p className="text-sm text-gray-500 mt-0.5">{step.description}</p>
51
+ </div>
52
+ </div>
53
+ );
54
+ })}
55
+ </div>
56
+ );
57
+ };
58
+
59
+ export default VerticalFlowSteps;
@@ -978,6 +978,16 @@ const Icon: FunctionComponent<ComponentProps> = ({
978
978
  d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 01-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z"
979
979
  />,
980
980
  );
981
+ } else if (icon === IconProp.IncomingCall) {
982
+ return getSvgWrapper(
983
+ <>
984
+ <path
985
+ strokeLinecap="round"
986
+ strokeLinejoin="round"
987
+ d="M14.25 9.75v-4.5m0 4.5h4.5m-4.5 0l6-6m-3 18c-8.284 0-15-6.716-15-15V4.5A2.25 2.25 0 014.5 2.25h1.372c.516 0 .966.351 1.091.852l1.106 4.423c.11.44-.054.902-.417 1.173l-1.293.97a1.062 1.062 0 00-.38 1.21 12.035 12.035 0 007.143 7.143c.441.162.928-.004 1.21-.38l.97-1.293a1.125 1.125 0 011.173-.417l4.423 1.106c.5.125.852.575.852 1.091V19.5a2.25 2.25 0 01-2.25 2.25h-2.25z"
988
+ />
989
+ </>,
990
+ );
981
991
  } else if (icon === IconProp.More) {
982
992
  return getSvgWrapper(
983
993
  <path
@@ -2,14 +2,98 @@ import React, { FunctionComponent, ReactElement } from "react";
2
2
 
3
3
  export interface ComponentProps {
4
4
  children: ReactElement | string | Array<ReactElement>;
5
+ showLineNumbers?: boolean | undefined;
6
+ height?: string | undefined;
7
+ title?: string | undefined;
5
8
  }
6
9
 
7
10
  const SimpleLogViewer: FunctionComponent<ComponentProps> = (
8
11
  props: ComponentProps,
9
12
  ): ReactElement => {
13
+ const showLineNumbers: boolean = props.showLineNumbers !== false;
14
+ const height: string = props.height || "400px";
15
+ const title: string | undefined = props.title;
16
+
17
+ const renderContent: () => ReactElement = (): ReactElement => {
18
+ if (typeof props.children === "string") {
19
+ const lines: Array<string> = props.children.split("\n");
20
+ return (
21
+ <>
22
+ {lines.map((line: string, index: number) => {
23
+ return (
24
+ <div
25
+ key={index}
26
+ className="flex hover:bg-slate-800/50 transition-colors"
27
+ >
28
+ {showLineNumbers && (
29
+ <span className="select-none text-slate-600 text-right pr-4 w-12 flex-shrink-0 border-r border-slate-800 mr-4">
30
+ {index + 1}
31
+ </span>
32
+ )}
33
+ <span className="text-slate-300 whitespace-pre-wrap break-all flex-1">
34
+ {line || " "}
35
+ </span>
36
+ </div>
37
+ );
38
+ })}
39
+ </>
40
+ );
41
+ }
42
+
43
+ if (Array.isArray(props.children)) {
44
+ return (
45
+ <>
46
+ {props.children.map(
47
+ (child: ReactElement, index: number): ReactElement => {
48
+ return (
49
+ <div
50
+ key={index}
51
+ className="flex hover:bg-slate-800/50 transition-colors"
52
+ >
53
+ {showLineNumbers && (
54
+ <span className="select-none text-slate-600 text-right pr-4 w-12 flex-shrink-0 border-r border-slate-800 mr-4">
55
+ {index + 1}
56
+ </span>
57
+ )}
58
+ <span className="text-slate-300 whitespace-pre-wrap break-all flex-1">
59
+ {child}
60
+ </span>
61
+ </div>
62
+ );
63
+ },
64
+ )}
65
+ </>
66
+ );
67
+ }
68
+
69
+ return (
70
+ <div className="text-slate-300 whitespace-pre-wrap break-all">
71
+ {props.children}
72
+ </div>
73
+ );
74
+ };
75
+
76
+ const scrollbarStyles: React.CSSProperties = {
77
+ maxHeight: height,
78
+ scrollbarWidth: "thin",
79
+ scrollbarColor: "#475569 #1e293b",
80
+ };
81
+
10
82
  return (
11
- <div className="text-gray-500 mt-5 text-sm h-96 overflow-y-auto overflow-x-hidden p-5 border-gray-50 border border-2 bg-gray-100 rounded">
12
- {props.children}
83
+ <div className="rounded-lg overflow-hidden border border-slate-700 bg-slate-900 shadow-lg">
84
+ {/* Title Header */}
85
+ {title && (
86
+ <div className="px-4 py-3 border-b border-slate-700 bg-slate-800">
87
+ <h3 className="text-sm font-medium text-slate-200">{title}</h3>
88
+ </div>
89
+ )}
90
+ {/* Log Content */}
91
+ <div
92
+ className="overflow-auto font-mono text-sm leading-6 p-4 [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-slate-800 [&::-webkit-scrollbar-thumb]:bg-slate-600 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:hover:bg-slate-500"
93
+ style={scrollbarStyles}
94
+ >
95
+ {renderContent()}
96
+ </div>
13
97
  </div>
14
98
  );
15
99
  };