@tma.js/sdk 0.11.3

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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/lib/browser.js +2 -0
  4. package/dist/lib/browser.js.map +1 -0
  5. package/dist/lib/index.cjs +2 -0
  6. package/dist/lib/index.cjs.map +1 -0
  7. package/dist/lib/index.mjs +2 -0
  8. package/dist/lib/index.mjs.map +1 -0
  9. package/dist/types/components/BackButton/BackButton.d.ts +44 -0
  10. package/dist/types/components/BackButton/index.d.ts +2 -0
  11. package/dist/types/components/BackButton/types.d.ts +9 -0
  12. package/dist/types/components/ClosingBehaviour/ClosingBehaviour.d.ts +35 -0
  13. package/dist/types/components/ClosingBehaviour/index.d.ts +2 -0
  14. package/dist/types/components/ClosingBehaviour/types.d.ts +7 -0
  15. package/dist/types/components/CloudStorage/CloudStorage.d.ts +47 -0
  16. package/dist/types/components/CloudStorage/index.d.ts +1 -0
  17. package/dist/types/components/HapticFeedback/HapticFeedback.d.ts +37 -0
  18. package/dist/types/components/HapticFeedback/index.d.ts +1 -0
  19. package/dist/types/components/InitData/InitData.d.ts +52 -0
  20. package/dist/types/components/InitData/index.d.ts +1 -0
  21. package/dist/types/components/MainButton/MainButton.d.ts +114 -0
  22. package/dist/types/components/MainButton/index.d.ts +2 -0
  23. package/dist/types/components/MainButton/types.d.ts +15 -0
  24. package/dist/types/components/Popup/Popup.d.ts +44 -0
  25. package/dist/types/components/Popup/index.d.ts +2 -0
  26. package/dist/types/components/Popup/types.d.ts +60 -0
  27. package/dist/types/components/Popup/utils.d.ts +7 -0
  28. package/dist/types/components/QRScanner/QRScanner.d.ts +40 -0
  29. package/dist/types/components/QRScanner/index.d.ts +2 -0
  30. package/dist/types/components/QRScanner/types.d.ts +7 -0
  31. package/dist/types/components/ThemeParams/ThemeParams.d.ts +73 -0
  32. package/dist/types/components/ThemeParams/index.d.ts +2 -0
  33. package/dist/types/components/ThemeParams/types.d.ts +9 -0
  34. package/dist/types/components/Viewport/Viewport.d.ts +108 -0
  35. package/dist/types/components/Viewport/index.d.ts +2 -0
  36. package/dist/types/components/Viewport/types.d.ts +10 -0
  37. package/dist/types/components/WebApp/WebApp.d.ts +145 -0
  38. package/dist/types/components/WebApp/index.d.ts +2 -0
  39. package/dist/types/components/WebApp/types.d.ts +11 -0
  40. package/dist/types/components/index.d.ts +11 -0
  41. package/dist/types/env.d.ts +8 -0
  42. package/dist/types/errors/MethodNotSupportedError.d.ts +6 -0
  43. package/dist/types/errors/ParameterNotSupportedError.d.ts +6 -0
  44. package/dist/types/errors/index.d.ts +2 -0
  45. package/dist/types/index.d.ts +8 -0
  46. package/dist/types/init/creators/createBackButton.d.ts +9 -0
  47. package/dist/types/init/creators/createClosingBehavior.d.ts +8 -0
  48. package/dist/types/init/creators/createMainButton.d.ts +11 -0
  49. package/dist/types/init/creators/createPostEvent.d.ts +7 -0
  50. package/dist/types/init/creators/createRequestIdGenerator.d.ts +5 -0
  51. package/dist/types/init/creators/createSyncedThemeParams.d.ts +7 -0
  52. package/dist/types/init/creators/createViewport.d.ts +10 -0
  53. package/dist/types/init/creators/createWebApp.d.ts +14 -0
  54. package/dist/types/init/creators/index.d.ts +8 -0
  55. package/dist/types/init/css.d.ts +57 -0
  56. package/dist/types/init/index.d.ts +2 -0
  57. package/dist/types/init/init.d.ts +6 -0
  58. package/dist/types/init/types.d.ts +107 -0
  59. package/dist/types/launch-params.d.ts +20 -0
  60. package/dist/types/state/State.d.ts +15 -0
  61. package/dist/types/state/index.d.ts +2 -0
  62. package/dist/types/state/types.d.ts +30 -0
  63. package/dist/types/storage.d.ts +48 -0
  64. package/dist/types/supports.d.ts +22 -0
  65. package/dist/types/theme-params.d.ts +18 -0
  66. package/dist/types/types.d.ts +14 -0
  67. package/dist/types/url.d.ts +7 -0
  68. package/package.json +67 -0
  69. package/src/components/BackButton/BackButton.ts +90 -0
  70. package/src/components/BackButton/index.ts +2 -0
  71. package/src/components/BackButton/types.ts +13 -0
  72. package/src/components/ClosingBehaviour/ClosingBehaviour.ts +62 -0
  73. package/src/components/ClosingBehaviour/index.ts +6 -0
  74. package/src/components/ClosingBehaviour/types.ts +12 -0
  75. package/src/components/CloudStorage/CloudStorage.ts +135 -0
  76. package/src/components/CloudStorage/index.ts +1 -0
  77. package/src/components/HapticFeedback/HapticFeedback.ts +62 -0
  78. package/src/components/HapticFeedback/index.ts +1 -0
  79. package/src/components/InitData/InitData.ts +116 -0
  80. package/src/components/InitData/index.ts +1 -0
  81. package/src/components/MainButton/MainButton.ts +243 -0
  82. package/src/components/MainButton/index.ts +2 -0
  83. package/src/components/MainButton/types.ts +20 -0
  84. package/src/components/Popup/Popup.ts +81 -0
  85. package/src/components/Popup/index.ts +8 -0
  86. package/src/components/Popup/types.ts +69 -0
  87. package/src/components/Popup/utils.ts +59 -0
  88. package/src/components/QRScanner/QRScanner.ts +87 -0
  89. package/src/components/QRScanner/index.ts +2 -0
  90. package/src/components/QRScanner/types.ts +11 -0
  91. package/src/components/ThemeParams/ThemeParams.ts +154 -0
  92. package/src/components/ThemeParams/index.ts +2 -0
  93. package/src/components/ThemeParams/types.ts +18 -0
  94. package/src/components/Viewport/Viewport.ts +197 -0
  95. package/src/components/Viewport/index.ts +2 -0
  96. package/src/components/Viewport/types.ts +14 -0
  97. package/src/components/WebApp/WebApp.ts +310 -0
  98. package/src/components/WebApp/index.ts +2 -0
  99. package/src/components/WebApp/types.ts +17 -0
  100. package/src/components/index.ts +11 -0
  101. package/src/env.ts +17 -0
  102. package/src/errors/MethodNotSupportedError.ts +9 -0
  103. package/src/errors/ParameterNotSupportedError.ts +9 -0
  104. package/src/errors/index.ts +2 -0
  105. package/src/index.ts +8 -0
  106. package/src/init/creators/createBackButton.ts +22 -0
  107. package/src/init/creators/createClosingBehavior.ts +22 -0
  108. package/src/init/creators/createMainButton.ts +56 -0
  109. package/src/init/creators/createPostEvent.ts +36 -0
  110. package/src/init/creators/createRequestIdGenerator.ts +13 -0
  111. package/src/init/creators/createSyncedThemeParams.ts +14 -0
  112. package/src/init/creators/createViewport.ts +50 -0
  113. package/src/init/creators/createWebApp.ts +49 -0
  114. package/src/init/creators/index.ts +8 -0
  115. package/src/init/css.ts +166 -0
  116. package/src/init/index.ts +2 -0
  117. package/src/init/init.ts +160 -0
  118. package/src/init/types.ts +133 -0
  119. package/src/launch-params.ts +70 -0
  120. package/src/state/State.ts +53 -0
  121. package/src/state/index.ts +2 -0
  122. package/src/state/types.ts +34 -0
  123. package/src/storage.ts +65 -0
  124. package/src/supports.ts +44 -0
  125. package/src/theme-params.ts +34 -0
  126. package/src/types.ts +28 -0
  127. package/src/url.ts +24 -0
@@ -0,0 +1,11 @@
1
+ import type { StateEvents } from '../../state/index.js';
2
+
3
+ export interface QRScannerState {
4
+ isOpened: boolean;
5
+ }
6
+
7
+ export type QRScannerEvents = StateEvents<QRScannerState>;
8
+
9
+ export type QRScannerEventName = keyof QRScannerEvents;
10
+
11
+ export type QRScannerEventListener<E extends QRScannerEventName> = QRScannerEvents[E];
@@ -0,0 +1,154 @@
1
+ import { EventEmitter } from '@tma.js/event-emitter';
2
+ import { on, request, type RequestOptions } from '@tma.js/bridge';
3
+ import { isColorDark } from '@tma.js/colors';
4
+
5
+ import type { RGB } from '@tma.js/colors';
6
+
7
+ import { parseThemeParams, type ThemeParamsType } from '../../theme-params.js';
8
+ import { State } from '../../state/index.js';
9
+
10
+ import type { ThemeParamsEvents, ThemeParamsState } from './types.js';
11
+
12
+ function prepareThemeParams(value: ThemeParamsType): ThemeParamsState {
13
+ const {
14
+ backgroundColor = null,
15
+ buttonTextColor = null,
16
+ buttonColor = null,
17
+ hintColor = null,
18
+ linkColor = null,
19
+ textColor = null,
20
+ secondaryBackgroundColor = null,
21
+ } = value;
22
+
23
+ return {
24
+ backgroundColor,
25
+ buttonTextColor,
26
+ buttonColor,
27
+ hintColor,
28
+ linkColor,
29
+ textColor,
30
+ secondaryBackgroundColor,
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Contains information about currently used theme by application.
36
+ * @see https://core.telegram.org/bots/webapps#themeparams
37
+ */
38
+ export class ThemeParams {
39
+ /**
40
+ * Requests fresh information about current theme.
41
+ * FIXME: Be careful using this function in desktop version of Telegram as
42
+ * long as method web_app_request_theme does not work on `macos` platform.
43
+ * @param options - method options.
44
+ */
45
+ static async request(options: RequestOptions = {}): Promise<ThemeParamsType> {
46
+ const { timeout = 1000, ...restOptions } = options;
47
+ const result = await request('web_app_request_theme', 'theme_changed', {
48
+ ...restOptions,
49
+ timeout,
50
+ });
51
+
52
+ return parseThemeParams(result.theme_params);
53
+ }
54
+
55
+ /**
56
+ * Synchronizes specified instance of ThemeParams with the actual value in the native
57
+ * application.
58
+ * @param themeParams - ThemeParams instance.
59
+ */
60
+ static sync(themeParams: ThemeParams): void {
61
+ on('theme_changed', (event) => {
62
+ themeParams.state.set(prepareThemeParams(parseThemeParams(event.theme_params)));
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Returns instance of ThemeParams which is synchronized with external
68
+ * environment.
69
+ * @param options - method options.
70
+ */
71
+ static async synced(options?: RequestOptions): Promise<ThemeParams> {
72
+ const params = await this.request(options);
73
+ const tp = new ThemeParams(params);
74
+
75
+ this.sync(tp);
76
+
77
+ return tp;
78
+ }
79
+
80
+ private readonly ee = new EventEmitter<ThemeParamsEvents>();
81
+
82
+ private readonly state: State<ThemeParamsState>;
83
+
84
+ constructor(params: ThemeParamsType) {
85
+ this.state = new State(prepareThemeParams(params), this.ee);
86
+ }
87
+
88
+ /**
89
+ * Returns background color.
90
+ */
91
+ get backgroundColor(): RGB | null {
92
+ return this.state.get('backgroundColor');
93
+ }
94
+
95
+ /**
96
+ * Returns button color.
97
+ */
98
+ get buttonColor(): RGB | null {
99
+ return this.state.get('buttonColor');
100
+ }
101
+
102
+ /**
103
+ * Returns button text color.
104
+ */
105
+ get buttonTextColor(): RGB | null {
106
+ return this.state.get('buttonTextColor');
107
+ }
108
+
109
+ /**
110
+ * Returns hint color.
111
+ */
112
+ get hintColor(): RGB | null {
113
+ return this.state.get('hintColor');
114
+ }
115
+
116
+ /**
117
+ * Returns true in case, current color scheme is recognized as dark. This
118
+ * value is calculated according to theme background color.
119
+ */
120
+ get isDark(): boolean {
121
+ return this.backgroundColor === null || isColorDark(this.backgroundColor);
122
+ }
123
+
124
+ /**
125
+ * Returns current link color.
126
+ */
127
+ get linkColor(): RGB | null {
128
+ return this.state.get('linkColor');
129
+ }
130
+
131
+ /**
132
+ * Adds new event listener.
133
+ */
134
+ on = this.ee.on.bind(this.ee);
135
+
136
+ /**
137
+ * Removes event listener.
138
+ */
139
+ off = this.ee.off.bind(this.ee);
140
+
141
+ /**
142
+ * Returns secondary background color.
143
+ */
144
+ get secondaryBackgroundColor(): RGB | null {
145
+ return this.state.get('secondaryBackgroundColor');
146
+ }
147
+
148
+ /**
149
+ * Returns text color.
150
+ */
151
+ get textColor(): RGB | null {
152
+ return this.state.get('textColor');
153
+ }
154
+ }
@@ -0,0 +1,2 @@
1
+ export * from './ThemeParams.js';
2
+ export * from './types.js';
@@ -0,0 +1,18 @@
1
+ import type { HasUndefined, If } from '@tma.js/util-types';
2
+
3
+ import type { ThemeParamsType } from '../../theme-params.js';
4
+ import type { StateEvents } from '../../state/index.js';
5
+
6
+ export type ThemeParamsState = {
7
+ [K in keyof ThemeParamsType]-?: If<
8
+ HasUndefined<ThemeParamsType[K]>,
9
+ Exclude<ThemeParamsType[K], undefined> | null,
10
+ ThemeParamsType[K]
11
+ >;
12
+ };
13
+
14
+ export type ThemeParamsEvents = StateEvents<ThemeParamsState>;
15
+
16
+ export type ThemeParamsEventName = keyof ThemeParamsEvents;
17
+
18
+ export type ThemeParamsEventListener<E extends ThemeParamsEventName> = ThemeParamsEvents[E];
@@ -0,0 +1,197 @@
1
+ import { EventEmitter } from '@tma.js/event-emitter';
2
+ import { on, postEvent as defaultPostEvent, request, type RequestOptions, type PostEvent } from '@tma.js/bridge';
3
+
4
+ import { State } from '../../state/index.js';
5
+
6
+ import type { ViewportEvents, ViewportState } from './types.js';
7
+
8
+ export interface RequestViewportResult {
9
+ height: number;
10
+ isStateStable: boolean;
11
+ isExpanded: boolean;
12
+ width: number;
13
+ }
14
+
15
+ /**
16
+ * Formats value to make it stay in bounds [0, +Inf).
17
+ * @param value - value to format.
18
+ */
19
+ function truncate(value: number): number {
20
+ return value < 0 ? 0 : value;
21
+ }
22
+
23
+ /**
24
+ * Contains information about current WebApp device viewport, its dimensions
25
+ * and state.
26
+ */
27
+ export class Viewport {
28
+ /**
29
+ * Requests fresh information about current viewport.
30
+ * FIXME: Be careful using this function in desktop version of Telegram as
31
+ * long as method web_app_request_viewport does not work on `macos` platform.
32
+ * @see Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/5
33
+ * @param options - method options.
34
+ */
35
+ static async request(options: RequestOptions = {}): Promise<RequestViewportResult> {
36
+ const { timeout = 1000, ...restOptions } = options;
37
+ const {
38
+ is_expanded: isExpanded,
39
+ is_state_stable: isStateStable,
40
+ ...rest
41
+ } = await request('web_app_request_viewport', 'viewport_changed', {
42
+ ...restOptions,
43
+ timeout,
44
+ });
45
+
46
+ return { ...rest, isExpanded, isStateStable };
47
+ }
48
+
49
+ /**
50
+ * Synchronizes specified instance of Viewport with the actual value in the native
51
+ * application.
52
+ * @param viewport - Viewport instance.
53
+ */
54
+ static sync(viewport: Viewport): void {
55
+ on('viewport_changed', (event) => {
56
+ const {
57
+ height,
58
+ width,
59
+ is_expanded: isExpanded,
60
+ is_state_stable: isStateStable,
61
+ } = event;
62
+ const formattedHeight = truncate(height);
63
+
64
+ viewport.state.set({
65
+ height: formattedHeight,
66
+ isExpanded,
67
+ width: truncate(width),
68
+ stableHeight: isStateStable ? formattedHeight : undefined,
69
+ });
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Returns initialized instance of Viewport which is synchronized with
75
+ * its actual state in Web Apps.
76
+ * @param options - method options.
77
+ */
78
+ static async synced(options: RequestOptions = {}): Promise<Viewport> {
79
+ const { height, isExpanded, width } = await this.request(options);
80
+ const viewport = new Viewport(height, width, height, isExpanded, options.postEvent);
81
+
82
+ this.sync(viewport);
83
+
84
+ return viewport;
85
+ }
86
+
87
+ private readonly ee = new EventEmitter<ViewportEvents>();
88
+
89
+ private readonly state: State<ViewportState>;
90
+
91
+ constructor(
92
+ height: number,
93
+ width: number,
94
+ stableHeight: number,
95
+ isExpanded: boolean,
96
+ private readonly postEvent: PostEvent = defaultPostEvent,
97
+ ) {
98
+ this.state = new State({
99
+ height: truncate(height),
100
+ isExpanded,
101
+ stableHeight: truncate(stableHeight),
102
+ width: truncate(width),
103
+ }, this.ee);
104
+ }
105
+
106
+ /**
107
+ * The current height of the visible area of the Web App.
108
+ *
109
+ * The application can display just the top part of the Web App, with its
110
+ * lower part remaining outside the screen area. From this position, the
111
+ * user can "pull" the Web App to its maximum height, while the bot can do
112
+ * the same by calling `expand` method. As the position of the Web App
113
+ * changes, the current height value of the visible area will be updated
114
+ * in real time.
115
+ *
116
+ * Please note that the refresh rate of this value is not sufficient
117
+ * to smoothly follow the lower border of the window. It should not be
118
+ * used to pin interface elements to the bottom of the visible area. It's
119
+ * more appropriate to use the value of the `stableHeight`
120
+ * field for this purpose.
121
+ *
122
+ * @see init
123
+ * @see expand
124
+ * @see stableHeight
125
+ */
126
+ get height(): number {
127
+ return this.state.get('height');
128
+ }
129
+
130
+ /**
131
+ * The height of the visible area of the Web App in its last stable state.
132
+ *
133
+ * The application can display just the top part of the Web App, with its
134
+ * lower part remaining outside the screen area. From this position,
135
+ * the user can "pull" the Web App to its maximum height, while the bot can
136
+ * do the same by calling `expand` method.
137
+ *
138
+ * Unlike the value of `height`, the value of `stableHeight`
139
+ * does not change as the position of the Web App changes with user
140
+ * gestures or during animations. The value of `stableHeight`
141
+ * will be updated after all gestures and animations are completed and
142
+ * the Web App reaches its final size.
143
+ *
144
+ * @see init
145
+ * @see expand
146
+ * @see height
147
+ */
148
+ get stableHeight(): number {
149
+ return this.state.get('stableHeight');
150
+ }
151
+
152
+ /**
153
+ * Returns true if the Web App is expanded to the maximum available height.
154
+ * Otherwise, if the Web App occupies part of the screen and can be expanded
155
+ * to the full height using `expand` method.
156
+ * @see expand
157
+ */
158
+ get isExpanded(): boolean {
159
+ return this.state.get('isExpanded');
160
+ }
161
+
162
+ /**
163
+ * Current viewport width.
164
+ */
165
+ get width(): number {
166
+ return this.state.get('width');
167
+ }
168
+
169
+ /**
170
+ * A method that expands the Web App to the maximum available height. To
171
+ * find out if the Web App is expanded to the maximum height, refer to the
172
+ * value of the `isExpanded`.
173
+ * @see isExpanded
174
+ */
175
+ expand(): void {
176
+ this.state.set('isExpanded', true);
177
+ this.postEvent('web_app_expand');
178
+ }
179
+
180
+ /**
181
+ * Returns true in case current viewport height is stable and is not going to
182
+ * change in the next moment.
183
+ */
184
+ get isStable(): boolean {
185
+ return this.stableHeight === this.height;
186
+ }
187
+
188
+ /**
189
+ * Adds new event listener.
190
+ */
191
+ on: typeof this.ee.on = this.ee.on.bind(this.ee);
192
+
193
+ /**
194
+ * Removes event listener.
195
+ */
196
+ off: typeof this.ee.off = this.ee.off.bind(this.ee);
197
+ }
@@ -0,0 +1,2 @@
1
+ export * from './Viewport.js';
2
+ export type { ViewportEvents, ViewportEventListener, ViewportEventName } from './types.js';
@@ -0,0 +1,14 @@
1
+ import type { StateEvents } from '../../state/index.js';
2
+
3
+ export interface ViewportState {
4
+ height: number;
5
+ isExpanded: boolean;
6
+ stableHeight: number;
7
+ width: number;
8
+ }
9
+
10
+ export type ViewportEvents = StateEvents<ViewportState>;
11
+
12
+ export type ViewportEventName = keyof ViewportEvents;
13
+
14
+ export type ViewportEventListener<E extends ViewportEventName> = ViewportEvents[E];