@tindalabs/shield 0.1.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 (118) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +357 -0
  3. package/dist/assess.d.ts +16 -0
  4. package/dist/assess.js +220 -0
  5. package/dist/config/default-extensions-config.json +103 -0
  6. package/dist/core/ContentProtector.d.ts +63 -0
  7. package/dist/core/ContentProtector.js +281 -0
  8. package/dist/core/index.d.ts +1 -0
  9. package/dist/core/index.js +2 -0
  10. package/dist/core/mediator/ContentProtectionMediator.d.ts +86 -0
  11. package/dist/core/mediator/ContentProtectionMediator.js +238 -0
  12. package/dist/core/mediator/eventDataTypes.d.ts +112 -0
  13. package/dist/core/mediator/eventDataTypes.js +23 -0
  14. package/dist/core/mediator/handlers/abstractEventHandler.d.ts +41 -0
  15. package/dist/core/mediator/handlers/abstractEventHandler.js +59 -0
  16. package/dist/core/mediator/handlers/devToolsEventHandler.d.ts +9 -0
  17. package/dist/core/mediator/handlers/devToolsEventHandler.js +95 -0
  18. package/dist/core/mediator/handlers/eventHandlerRegistry.d.ts +9 -0
  19. package/dist/core/mediator/handlers/eventHandlerRegistry.js +34 -0
  20. package/dist/core/mediator/handlers/extensionEventHandlers.d.ts +40 -0
  21. package/dist/core/mediator/handlers/extensionEventHandlers.js +140 -0
  22. package/dist/core/mediator/handlers/iFrameEventHandlers.d.ts +27 -0
  23. package/dist/core/mediator/handlers/iFrameEventHandlers.js +93 -0
  24. package/dist/core/mediator/handlers/screenShotEventHandlers.d.ts +34 -0
  25. package/dist/core/mediator/handlers/screenShotEventHandlers.js +111 -0
  26. package/dist/core/mediator/protection-event.d.ts +77 -0
  27. package/dist/core/mediator/protection-event.js +32 -0
  28. package/dist/core/mediator/types.d.ts +105 -0
  29. package/dist/core/mediator/types.js +1 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.js +7 -0
  32. package/dist/otel.d.ts +24 -0
  33. package/dist/otel.js +83 -0
  34. package/dist/policy.d.ts +98 -0
  35. package/dist/policy.js +97 -0
  36. package/dist/strategies/AbstractStrategy.d.ts +124 -0
  37. package/dist/strategies/AbstractStrategy.js +256 -0
  38. package/dist/strategies/ClipboardStrategy.d.ts +67 -0
  39. package/dist/strategies/ClipboardStrategy.js +291 -0
  40. package/dist/strategies/ContextMenuStrategy.d.ts +60 -0
  41. package/dist/strategies/ContextMenuStrategy.js +454 -0
  42. package/dist/strategies/DevToolsStrategy.d.ts +55 -0
  43. package/dist/strategies/DevToolsStrategy.js +314 -0
  44. package/dist/strategies/ExtensionStrategy.d.ts +66 -0
  45. package/dist/strategies/ExtensionStrategy.js +486 -0
  46. package/dist/strategies/IFrameStrategy.d.ts +49 -0
  47. package/dist/strategies/IFrameStrategy.js +255 -0
  48. package/dist/strategies/KeyboardStrategy.d.ts +35 -0
  49. package/dist/strategies/KeyboardStrategy.js +130 -0
  50. package/dist/strategies/PrintStrategy.d.ts +47 -0
  51. package/dist/strategies/PrintStrategy.js +201 -0
  52. package/dist/strategies/ScreenshotStrategy.d.ts +90 -0
  53. package/dist/strategies/ScreenshotStrategy.js +502 -0
  54. package/dist/strategies/SelectionStrategy.d.ts +49 -0
  55. package/dist/strategies/SelectionStrategy.js +216 -0
  56. package/dist/strategies/WatermarkStrategy.d.ts +56 -0
  57. package/dist/strategies/WatermarkStrategy.js +287 -0
  58. package/dist/strategies/index.d.ts +10 -0
  59. package/dist/strategies/index.js +11 -0
  60. package/dist/types/assessment.d.ts +62 -0
  61. package/dist/types/assessment.js +1 -0
  62. package/dist/types/index.d.ts +278 -0
  63. package/dist/types/index.js +17 -0
  64. package/dist/utils/DOMObserver.d.ts +68 -0
  65. package/dist/utils/DOMObserver.js +134 -0
  66. package/dist/utils/base/LoggableComponent.d.ts +44 -0
  67. package/dist/utils/base/LoggableComponent.js +56 -0
  68. package/dist/utils/detectors/AbstractDevToolsDetector.d.ts +98 -0
  69. package/dist/utils/detectors/AbstractDevToolsDetector.js +127 -0
  70. package/dist/utils/detectors/dateToStringDetector.d.ts +43 -0
  71. package/dist/utils/detectors/dateToStringDetector.js +96 -0
  72. package/dist/utils/detectors/debugLibDetector.d.ts +64 -0
  73. package/dist/utils/detectors/debugLibDetector.js +195 -0
  74. package/dist/utils/detectors/debuggerDetector.d.ts +51 -0
  75. package/dist/utils/detectors/debuggerDetector.js +211 -0
  76. package/dist/utils/detectors/defineGetterDetector.d.ts +48 -0
  77. package/dist/utils/detectors/defineGetterDetector.js +150 -0
  78. package/dist/utils/detectors/detectorInterface.d.ts +36 -0
  79. package/dist/utils/detectors/detectorInterface.js +1 -0
  80. package/dist/utils/detectors/devToolsDetectorManager.d.ts +88 -0
  81. package/dist/utils/detectors/devToolsDetectorManager.js +243 -0
  82. package/dist/utils/detectors/funcToStringDetector.d.ts +43 -0
  83. package/dist/utils/detectors/funcToStringDetector.js +90 -0
  84. package/dist/utils/detectors/regToStringDetector.d.ts +43 -0
  85. package/dist/utils/detectors/regToStringDetector.js +129 -0
  86. package/dist/utils/detectors/sizeDetector.d.ts +54 -0
  87. package/dist/utils/detectors/sizeDetector.js +134 -0
  88. package/dist/utils/detectors/timingDetector.d.ts +55 -0
  89. package/dist/utils/detectors/timingDetector.js +143 -0
  90. package/dist/utils/dom.d.ts +20 -0
  91. package/dist/utils/dom.js +83 -0
  92. package/dist/utils/environment.d.ts +29 -0
  93. package/dist/utils/environment.js +267 -0
  94. package/dist/utils/eventManager.d.ts +162 -0
  95. package/dist/utils/eventManager.js +548 -0
  96. package/dist/utils/index.d.ts +2 -0
  97. package/dist/utils/index.js +3 -0
  98. package/dist/utils/intervalManager.d.ts +91 -0
  99. package/dist/utils/intervalManager.js +221 -0
  100. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.d.ts +41 -0
  101. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.js +135 -0
  102. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.d.ts +18 -0
  103. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.js +195 -0
  104. package/dist/utils/logging/simple/Loggable.d.ts +33 -0
  105. package/dist/utils/logging/simple/Loggable.js +1 -0
  106. package/dist/utils/logging/simple/LoggingDelegate.d.ts +42 -0
  107. package/dist/utils/logging/simple/LoggingDelegate.js +53 -0
  108. package/dist/utils/logging/simple/SimpleLoggingService.d.ts +39 -0
  109. package/dist/utils/logging/simple/SimpleLoggingService.js +58 -0
  110. package/dist/utils/orientation.d.ts +15 -0
  111. package/dist/utils/orientation.js +32 -0
  112. package/dist/utils/protectedContentManager.d.ts +155 -0
  113. package/dist/utils/protectedContentManager.js +424 -0
  114. package/dist/utils/securityOverlayManager.d.ts +253 -0
  115. package/dist/utils/securityOverlayManager.js +786 -0
  116. package/dist/utils/timeoutManager.d.ts +50 -0
  117. package/dist/utils/timeoutManager.js +113 -0
  118. package/package.json +61 -0
@@ -0,0 +1,134 @@
1
+ import { isBrowser, getBrowser } from "../environment";
2
+ import { eventManager } from "../eventManager";
3
+ import { AbstractDevToolsDetector, DetectorErrorType } from "./AbstractDevToolsDetector";
4
+ /**
5
+ * Utility class for detecting DevTools using window size differences
6
+ * This approach works by detecting unusual differences between outer and inner window dimensions
7
+ * that typically occur when DevTools are open
8
+ */
9
+ export class SizeDetector extends AbstractDevToolsDetector {
10
+ /**
11
+ * Create a new SizeDetector
12
+ * @param options Configuration options
13
+ */
14
+ constructor(options = {}) {
15
+ super("SizeDetector", options);
16
+ this.resizeEventId = "";
17
+ this.widthThreshold = options.widthThreshold || 200;
18
+ this.heightThreshold = options.heightThreshold || 300;
19
+ // Initialize resize listener
20
+ this.initResizeListener();
21
+ this.logger.log(`Initialized with thresholds - width: ${this.widthThreshold}px, height: ${this.heightThreshold}px`);
22
+ }
23
+ /**
24
+ * Initialize resize event listener
25
+ */
26
+ initResizeListener() {
27
+ this.safeExecute("initResizeListener", DetectorErrorType.INITIALIZATION_ERROR, () => {
28
+ if (!isBrowser())
29
+ return;
30
+ // Create resize handler
31
+ const resizeHandler = () => {
32
+ // Use setTimeout to avoid too many checks during resize
33
+ setTimeout(() => {
34
+ this.checkDevTools();
35
+ }, 100);
36
+ };
37
+ // Register resize event using eventManager
38
+ this.resizeEventId = eventManager.addEventListener(window, "resize", resizeHandler, "SizeDetector", {
39
+ passive: true,
40
+ priority: 5, // Medium-high priority
41
+ });
42
+ // Perform initial check
43
+ this.checkDevTools();
44
+ this.logger.log(`Resize listener initialized with event ID: ${this.resizeEventId}`);
45
+ });
46
+ }
47
+ /**
48
+ * Calculate screen zoom ratio
49
+ * @returns The screen zoom ratio or false if it can't be determined
50
+ */
51
+ getScreenZoomRatio() {
52
+ return (this.safeExecute("getScreenZoomRatio", DetectorErrorType.DETECTION_ERROR, () => {
53
+ if (!isBrowser())
54
+ return false;
55
+ // Try to use devicePixelRatio first (most reliable)
56
+ if (typeof window.devicePixelRatio !== "undefined") {
57
+ return window.devicePixelRatio;
58
+ }
59
+ // Fallback to screen properties for older browsers
60
+ const screen = window.screen;
61
+ if (!screen)
62
+ return false;
63
+ if (screen.deviceXDPI && screen.logicalXDPI) {
64
+ return screen.deviceXDPI / screen.logicalXDPI;
65
+ }
66
+ return false;
67
+ }) || false);
68
+ }
69
+ /**
70
+ * Check if DevTools is open using window size differences
71
+ */
72
+ checkDevTools() {
73
+ if (this.isChecking || !isBrowser())
74
+ return;
75
+ this.isChecking = true;
76
+ this.safeExecute("checkDevTools", DetectorErrorType.DETECTION_ERROR, () => {
77
+ // Get screen zoom ratio
78
+ const screenRatio = this.getScreenZoomRatio();
79
+ // If we can't get the screen ratio, we can't reliably detect
80
+ if (screenRatio === false) {
81
+ this.isChecking = false;
82
+ return;
83
+ }
84
+ // Calculate size differences accounting for zoom
85
+ const widthDiff = window.outerWidth - window.innerWidth * screenRatio;
86
+ const heightDiff = window.outerHeight - window.innerHeight * screenRatio;
87
+ // Check if differences exceed thresholds
88
+ const widthUneven = widthDiff > this.widthThreshold;
89
+ const heightUneven = heightDiff > this.heightThreshold;
90
+ // DevTools is considered open if either dimension is uneven
91
+ const isOpen = widthUneven || heightUneven;
92
+ // Log detailed size information in debug mode
93
+ this.logger.log(`Window sizes - outer: ${window.outerWidth}x${window.outerHeight}, inner: ${window.innerWidth}x${window.innerHeight}, zoom: ${screenRatio}`);
94
+ this.logger.log(`Size differences - width: ${widthDiff.toFixed(2)}px, height: ${heightDiff.toFixed(2)}px`);
95
+ // Update DevTools state and notify listeners if changed
96
+ this.updateDevToolsState(isOpen);
97
+ this.isChecking = false;
98
+ });
99
+ // Ensure isChecking is reset even if an error occurs
100
+ if (this.isChecking) {
101
+ this.isChecking = false;
102
+ }
103
+ }
104
+ /**
105
+ * Clean up resources
106
+ */
107
+ dispose() {
108
+ this.safeExecute("dispose", DetectorErrorType.DISPOSAL_ERROR, () => {
109
+ if (isBrowser() && this.resizeEventId) {
110
+ // Remove the resize event listener using eventManager
111
+ eventManager.removeEventListener(window, this.resizeEventId);
112
+ this.resizeEventId = "";
113
+ this.logger.log("Removed resize event listener");
114
+ this.logger.log("Disposed");
115
+ }
116
+ });
117
+ super.dispose();
118
+ }
119
+ /**
120
+ * Check if this detector is supported in the current browser
121
+ * @returns True if supported
122
+ */
123
+ static isSupported() {
124
+ if (!isBrowser())
125
+ return false;
126
+ const browser = getBrowser();
127
+ const isIframe = window.self !== window.top;
128
+ // Not supported in iframes or Edge
129
+ if (isIframe || browser.name === "edge") {
130
+ return false;
131
+ }
132
+ return true;
133
+ }
134
+ }
@@ -0,0 +1,55 @@
1
+ import { AbstractDevToolsDetector } from "./AbstractDevToolsDetector";
2
+ import { DevToolsDetectorOptions } from "./detectorInterface";
3
+ /**
4
+ * Options for the TimingDetector
5
+ */
6
+ export interface TimingDetectorOptions extends DevToolsDetectorOptions {
7
+ /**
8
+ * Threshold multiplier for detection
9
+ * Higher values make detection less sensitive
10
+ */
11
+ thresholdMultiplier?: number;
12
+ }
13
+ /**
14
+ * Utility class for detecting DevTools using console timing differences
15
+ * This approach works especially well in Firefox
16
+ */
17
+ export declare class TimingDetector extends AbstractDevToolsDetector {
18
+ private largeObjectArray;
19
+ private maxPrintTime;
20
+ private thresholdMultiplier;
21
+ /**
22
+ * Create a new TimingDetector
23
+ * @param options Configuration options
24
+ */
25
+ constructor(options?: TimingDetectorOptions);
26
+ /**
27
+ * Initialize the large object array used for timing tests
28
+ */
29
+ private initLargeObjectArray;
30
+ /**
31
+ * Create a large object for timing tests
32
+ */
33
+ private createLargeObject;
34
+ /**
35
+ * Create an array of large objects for timing tests
36
+ */
37
+ private createLargeObjectArray;
38
+ /**
39
+ * Calculate execution time of a function
40
+ */
41
+ private calculateTime;
42
+ /**
43
+ * Check if DevTools is open using console timing
44
+ */
45
+ checkDevTools(): void;
46
+ /**
47
+ * Clean up resources
48
+ */
49
+ dispose(): void;
50
+ /**
51
+ * Check if this detector is supported in the current browser
52
+ * @returns True if supported
53
+ */
54
+ static isSupported(): boolean;
55
+ }
@@ -0,0 +1,143 @@
1
+ import { getBrowser, isBrowser, isMobile } from "../environment";
2
+ import { AbstractDevToolsDetector, DetectorErrorType } from "./AbstractDevToolsDetector";
3
+ /**
4
+ * Utility class for detecting DevTools using console timing differences
5
+ * This approach works especially well in Firefox
6
+ */
7
+ export class TimingDetector extends AbstractDevToolsDetector {
8
+ /**
9
+ * Create a new TimingDetector
10
+ * @param options Configuration options
11
+ */
12
+ constructor(options = {}) {
13
+ super("TimingDetector", options);
14
+ this.largeObjectArray = [];
15
+ this.maxPrintTime = 0;
16
+ this.thresholdMultiplier = options.thresholdMultiplier || 10; //DIFFERENCE BETWEEN .log AND .table
17
+ // Initialize the large object array
18
+ this.initLargeObjectArray();
19
+ this.logger.log("Initialized with threshold multiplier:", this.thresholdMultiplier);
20
+ }
21
+ /**
22
+ * Initialize the large object array used for timing tests
23
+ */
24
+ initLargeObjectArray() {
25
+ this.safeExecute("initLargeObjectArray", DetectorErrorType.INITIALIZATION_ERROR, () => {
26
+ if (!isBrowser())
27
+ return;
28
+ this.largeObjectArray = this.createLargeObjectArray();
29
+ this.maxPrintTime = 0;
30
+ this.logger.log("Large object array initialized with size:", this.largeObjectArray.length);
31
+ });
32
+ }
33
+ /**
34
+ * Create a large object for timing tests
35
+ */
36
+ createLargeObject() {
37
+ return (this.safeExecute("createLargeObject", DetectorErrorType.INITIALIZATION_ERROR, () => {
38
+ const largeObject = {};
39
+ for (let i = 0; i < 500; i++) {
40
+ largeObject[`${i}`] = `${i}`;
41
+ }
42
+ return largeObject;
43
+ }) || {});
44
+ }
45
+ /**
46
+ * Create an array of large objects for timing tests
47
+ */
48
+ createLargeObjectArray() {
49
+ return (this.safeExecute("createLargeObjectArray", DetectorErrorType.INITIALIZATION_ERROR, () => {
50
+ const largeObject = this.createLargeObject();
51
+ const largeObjectArray = [];
52
+ for (let i = 0; i < 50; i++) {
53
+ largeObjectArray.push(largeObject);
54
+ }
55
+ return largeObjectArray;
56
+ }) || []);
57
+ }
58
+ /**
59
+ * Calculate execution time of a function
60
+ */
61
+ calculateTime(func) {
62
+ return (this.safeExecute("calculateTime", DetectorErrorType.DETECTION_ERROR, () => {
63
+ const start = performance.now();
64
+ func();
65
+ return performance.now() - start;
66
+ }) || 0);
67
+ }
68
+ /**
69
+ * Check if DevTools is open using console timing
70
+ */
71
+ checkDevTools() {
72
+ if (this.isChecking || !isBrowser())
73
+ return;
74
+ this.isChecking = true;
75
+ this.safeExecute("checkDevTools", DetectorErrorType.DETECTION_ERROR, () => {
76
+ // Measure time to print large object array using console.table
77
+ const tablePrintTime = this.calculateTime(() => {
78
+ console.table(this.largeObjectArray.slice(0, 8)); // Use a smaller slice to avoid freezing
79
+ });
80
+ // Measure time to print large object array using console.log
81
+ const logPrintTime = this.calculateTime(() => {
82
+ console.log(this.largeObjectArray.slice(0, 8)); // Use a smaller slice to avoid freezing
83
+ });
84
+ // Update max print time
85
+ this.maxPrintTime = Math.max(this.maxPrintTime, logPrintTime);
86
+ // Clear console
87
+ console.clear();
88
+ // Skip detection if we don't have valid measurements yet
89
+ if (tablePrintTime === 0 || this.maxPrintTime === 0) {
90
+ this.isChecking = false;
91
+ return;
92
+ }
93
+ // If table print time is significantly higher than max log print time,
94
+ // DevTools is likely open
95
+ const isOpen = tablePrintTime > this.maxPrintTime * this.thresholdMultiplier;
96
+ // Update state and notify listeners if changed
97
+ this.updateDevToolsState(isOpen);
98
+ this.logger.log(`Timing check - table: ${tablePrintTime.toFixed(2)}ms, log: ${logPrintTime.toFixed(2)}ms, max: ${this.maxPrintTime.toFixed(2)}ms, ratio: ${(tablePrintTime / this.maxPrintTime).toFixed(2)}x`);
99
+ this.isChecking = false;
100
+ });
101
+ }
102
+ /**
103
+ * Clean up resources
104
+ */
105
+ dispose() {
106
+ this.safeExecute("dispose", DetectorErrorType.DISPOSAL_ERROR, () => {
107
+ this.largeObjectArray = [];
108
+ this.maxPrintTime = 0;
109
+ this.logger.log("Disposed");
110
+ });
111
+ super.dispose();
112
+ }
113
+ /**
114
+ * Check if this detector is supported in the current browser
115
+ * @returns True if supported
116
+ */
117
+ static isSupported() {
118
+ if (!isBrowser())
119
+ return false;
120
+ // Check if required console methods exist
121
+ if (typeof console === "undefined" || typeof console.table !== "function" || typeof console.log !== "function") {
122
+ return false;
123
+ }
124
+ // Check if performance API is available
125
+ if (typeof performance === "undefined" || typeof performance.now !== "function") {
126
+ return false;
127
+ }
128
+ // Get browser info
129
+ const browser = getBrowser();
130
+ const isMobileDevice = isMobile();
131
+ // This detector works best in Firefox and desktop browsers
132
+ // It's less reliable in mobile browsers and some WebKit browsers
133
+ // Not recommended for mobile Chrome or Edge
134
+ if (isMobileDevice && (browser.name === "chrome" || browser.name === "edge")) {
135
+ return false;
136
+ }
137
+ // Not recommended for Safari (desktop or mobile) as it has inconsistent timing behavior
138
+ if (browser.name === "safari") {
139
+ return false;
140
+ }
141
+ return true;
142
+ }
143
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Safely add event listener with error handling
3
+ */
4
+ export declare const safeAddEventListener: (element: HTMLElement | Document | Window, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions) => boolean;
5
+ /**
6
+ * Safely remove event listener with error handling
7
+ */
8
+ export declare const safeRemoveEventListener: (element: HTMLElement | Document | Window, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions) => boolean;
9
+ /**
10
+ * Create and inject a style element
11
+ */
12
+ export declare const injectStyles: (css: string, id?: string) => HTMLStyleElement | null;
13
+ /**
14
+ * Remove a style element by ID
15
+ */
16
+ export declare const removeStyles: (id: string) => boolean;
17
+ /**
18
+ * Create an element with attributes and styles
19
+ */
20
+ export declare const createElement: <T extends HTMLElement>(tag: string, attributes?: Record<string, string>, styles?: Partial<CSSStyleDeclaration>) => T;
@@ -0,0 +1,83 @@
1
+ // DOM UTILITIES
2
+ /**
3
+ * Safely add event listener with error handling
4
+ */
5
+ export const safeAddEventListener = (element, event, handler, options) => {
6
+ try {
7
+ element.addEventListener(event, handler, options);
8
+ return true;
9
+ }
10
+ catch (error) {
11
+ console.error(`Failed to add event listener for ${event}:`, error);
12
+ return false;
13
+ }
14
+ };
15
+ /**
16
+ * Safely remove event listener with error handling
17
+ */
18
+ export const safeRemoveEventListener = (element, event, handler, options) => {
19
+ try {
20
+ element.removeEventListener(event, handler, options);
21
+ return true;
22
+ }
23
+ catch (error) {
24
+ console.error(`Failed to remove event listener for ${event}:`, error);
25
+ return false;
26
+ }
27
+ };
28
+ /**
29
+ * Create and inject a style element
30
+ */
31
+ export const injectStyles = (css, id) => {
32
+ if (typeof document === 'undefined')
33
+ return null;
34
+ try {
35
+ const style = document.createElement('style');
36
+ style.setAttribute('type', 'text/css');
37
+ if (id) {
38
+ style.id = id;
39
+ }
40
+ style.textContent = css;
41
+ document.head.appendChild(style);
42
+ return style;
43
+ }
44
+ catch (error) {
45
+ console.error('Failed to inject styles:', error);
46
+ return null;
47
+ }
48
+ };
49
+ /**
50
+ * Remove a style element by ID
51
+ */
52
+ export const removeStyles = (id) => {
53
+ if (typeof document === 'undefined')
54
+ return false;
55
+ try {
56
+ const style = document.getElementById(id);
57
+ if (style && style.parentNode) {
58
+ style.parentNode.removeChild(style);
59
+ return true;
60
+ }
61
+ return false;
62
+ }
63
+ catch (error) {
64
+ console.error(`Failed to remove styles with ID ${id}:`, error);
65
+ return false;
66
+ }
67
+ };
68
+ /**
69
+ * Create an element with attributes and styles
70
+ */
71
+ export const createElement = (tag, attributes = {}, styles = {}) => {
72
+ if (typeof document === 'undefined') {
73
+ throw new Error('Document is not available');
74
+ }
75
+ const element = document.createElement(tag);
76
+ // Set attributes
77
+ Object.entries(attributes).forEach(([key, value]) => {
78
+ element.setAttribute(key, value);
79
+ });
80
+ // Set styles
81
+ Object.assign(element.style, styles);
82
+ return element;
83
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Detect browser environment
3
+ */
4
+ export declare const isBrowser: () => boolean;
5
+ /**
6
+ * Detect mobile device
7
+ */
8
+ export declare const isMobile: () => boolean;
9
+ /**
10
+ * Detect specific browser
11
+ */
12
+ export declare const getBrowser: () => {
13
+ name: string;
14
+ version: string;
15
+ };
16
+ /**
17
+ * Detect operating system
18
+ */
19
+ export declare const getOS: () => {
20
+ name: "mac" | "linux" | "windows" | "unknown";
21
+ };
22
+ /**
23
+ * Check if print is supported
24
+ */
25
+ export declare const isPrintSupported: () => boolean;
26
+ /**
27
+ * Check if beforeprint event is supported
28
+ */
29
+ export declare const isBeforePrintSupported: () => boolean;