tgwidget 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -6
- package/dist/builder.d.ts +7 -5
- package/dist/builder.js +19 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/parser.js +33 -5
- package/dist/pattern.d.ts +2 -0
- package/dist/pattern.js +40 -0
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,13 +38,19 @@ When a user completes the widget, the result comes back via deep link `t.me/your
|
|
|
38
38
|
```typescript
|
|
39
39
|
import { parseDate, parseColor, parseSchedule } from "tgwidget";
|
|
40
40
|
|
|
41
|
-
// Date result
|
|
41
|
+
// Date result — includes native Date object
|
|
42
42
|
const result = parseDate("2025-03-15", { mode: "date" });
|
|
43
|
-
//
|
|
43
|
+
// result.date === '2025-03-15'
|
|
44
|
+
// result.dateObj === Date(2025, 2, 15)
|
|
45
|
+
|
|
46
|
+
// Datetime — native Date with time set
|
|
47
|
+
const result = parseDate("2025-03-15_14-30", { mode: "datetime" });
|
|
48
|
+
// result.dateObj — Date object with date and time
|
|
44
49
|
|
|
45
50
|
// Unix timestamp
|
|
46
51
|
const result = parseDate("1710460800_1718236800", { mode: "date-range", format: "unix-s" });
|
|
47
|
-
//
|
|
52
|
+
// result.dateObj, result.dateEndObj — native Date objects
|
|
53
|
+
// result.timestamp === 1710460800
|
|
48
54
|
|
|
49
55
|
// Color
|
|
50
56
|
const result = parseColor("FF6600", { format: "hex" });
|
|
@@ -55,21 +61,84 @@ const result = parseSchedule("09001800090018000000000009001800090018000000000000
|
|
|
55
61
|
// [{ enabled: true, start: '09:00', end: '18:00' }, ...]
|
|
56
62
|
```
|
|
57
63
|
|
|
64
|
+
All parsers automatically handle Telegram bot command prefixes — you can pass raw `/start payload` strings directly:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const result = parseDate("/start 2025-03-15", { mode: "date" });
|
|
68
|
+
// result.dateObj — Date(2025, 2, 15)
|
|
69
|
+
|
|
70
|
+
const result = parseColor("/start FF6600", { format: "hex" });
|
|
71
|
+
// result.hex === '#FF6600'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Pattern (informational format string)
|
|
75
|
+
|
|
76
|
+
Each widget exposes a `.pattern` property — a human-readable format hint you can show to users:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const widget = tgwidget("your_bot").date({ mode: "datetime" });
|
|
80
|
+
widget.pattern; // "YYYY-MM-DD HH:MM"
|
|
81
|
+
|
|
82
|
+
const widget2 = tgwidget("your_bot").date({ mode: "date", order: "dmy" });
|
|
83
|
+
widget2.pattern; // "DD-MM-YYYY"
|
|
84
|
+
|
|
85
|
+
const widget3 = tgwidget("your_bot").color({ format: "hex" });
|
|
86
|
+
widget3.pattern; // "#RRGGBB"
|
|
87
|
+
|
|
88
|
+
// Use in bot messages:
|
|
89
|
+
await ctx.reply(`Введите дату в формате ${widget.pattern}`);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
You can also use the standalone `getPattern(widget, payload)` function directly.
|
|
93
|
+
|
|
94
|
+
### Widget-level parsing with `parse()`
|
|
95
|
+
|
|
96
|
+
If you keep a reference to the widget builder, you can call `.parse()` directly — it automatically uses the configured widget type and options. The return type is inferred from the widget type:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const widget = tgwidget("your_bot").date({ mode: "datetime" });
|
|
100
|
+
const url = widget.url();
|
|
101
|
+
|
|
102
|
+
// Later, when the user completes the widget:
|
|
103
|
+
const result = widget.parse("/start 2025-03-15_14-30");
|
|
104
|
+
// result is DateResult (type-safe!)
|
|
105
|
+
// result.dateObj — native Date object
|
|
106
|
+
```
|
|
107
|
+
|
|
58
108
|
## API
|
|
59
109
|
|
|
60
110
|
### `tgwidget(botUsername)`
|
|
61
111
|
|
|
62
112
|
Create a widget builder. Returns a chainable `TgWidget` instance.
|
|
63
113
|
|
|
64
|
-
- `.date({ mode?, format?, order? })` — Date/time picker
|
|
65
|
-
- `.color({ format? })` — Color picker
|
|
66
|
-
- `.schedule()` — Weekly schedule
|
|
114
|
+
- `.date({ mode?, format?, order? })` — Date/time picker → `TgWidget<"date">`
|
|
115
|
+
- `.color({ format? })` — Color picker → `TgWidget<"color">`
|
|
116
|
+
- `.schedule()` — Weekly schedule → `TgWidget<"schedule">`
|
|
67
117
|
- `.style({ colorScheme?, accent?, tint?, liquidGlass?, adaptTgTheme?, adoptTgPalette? })` — Styling
|
|
68
118
|
- `.url(baseUrl?)` — Generate the final URL
|
|
69
119
|
- `.payload()` — Get the raw payload object
|
|
120
|
+
- `.pattern` — Human-readable format string (e.g. `"YYYY-MM-DD HH:MM"`)
|
|
121
|
+
- `.parse(value)` — Parse a widget result string (return type matches widget type)
|
|
70
122
|
|
|
71
123
|
### Parsers
|
|
72
124
|
|
|
73
125
|
- `parseDate(value, { mode?, format?, order? })` → `DateResult`
|
|
74
126
|
- `parseColor(value, { format? })` → `ColorResult`
|
|
75
127
|
- `parseSchedule(value)` → `ScheduleDay[]`
|
|
128
|
+
|
|
129
|
+
### Result types
|
|
130
|
+
|
|
131
|
+
#### `DateResult`
|
|
132
|
+
- `date`, `time`, `dateEnd`, `timeEnd` — string representations
|
|
133
|
+
- `timestamp`, `timestampEnd` — raw integer timestamps (unix modes)
|
|
134
|
+
- `dateObj`, `dateEndObj` — native `Date` objects
|
|
135
|
+
|
|
136
|
+
#### `ColorResult`
|
|
137
|
+
- `raw` — original value string
|
|
138
|
+
- `hex` — e.g. `'#FF6600'`
|
|
139
|
+
- `rgb` — e.g. `[255, 102, 0]`
|
|
140
|
+
- `hsl` — e.g. `[24, 100, 50]`
|
|
141
|
+
|
|
142
|
+
#### `ScheduleDay`
|
|
143
|
+
- `enabled` — whether the day is active
|
|
144
|
+
- `start`, `end` — time strings e.g. `'09:00'`
|
package/dist/builder.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { DateMode, DateFormat, DateOrder, ColorFormat, ColorScheme } from "./types";
|
|
2
|
-
export declare class TgWidget {
|
|
1
|
+
import type { DateMode, DateFormat, DateOrder, ColorFormat, ColorScheme, WidgetType, ParseResult } from "./types";
|
|
2
|
+
export declare class TgWidget<T extends WidgetType | null = null> {
|
|
3
3
|
private _botUsername;
|
|
4
4
|
private _widget;
|
|
5
5
|
private _payload;
|
|
@@ -9,11 +9,11 @@ export declare class TgWidget {
|
|
|
9
9
|
mode?: DateMode;
|
|
10
10
|
format?: DateFormat;
|
|
11
11
|
order?: DateOrder;
|
|
12
|
-
}):
|
|
12
|
+
}): TgWidget<"date">;
|
|
13
13
|
color(opts?: {
|
|
14
14
|
format?: ColorFormat;
|
|
15
|
-
}):
|
|
16
|
-
schedule():
|
|
15
|
+
}): TgWidget<"color">;
|
|
16
|
+
schedule(): TgWidget<"schedule">;
|
|
17
17
|
style(opts?: {
|
|
18
18
|
colorScheme?: ColorScheme;
|
|
19
19
|
accent?: string;
|
|
@@ -25,5 +25,7 @@ export declare class TgWidget {
|
|
|
25
25
|
private _buildPayload;
|
|
26
26
|
url(baseUrl?: string): string;
|
|
27
27
|
payload(): Record<string, unknown>;
|
|
28
|
+
get pattern(): string;
|
|
29
|
+
parse(value: string): ParseResult<T>;
|
|
28
30
|
}
|
|
29
31
|
export declare function tgwidget(botUsername: string): TgWidget;
|
package/dist/builder.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { parseDate, parseColor, parseSchedule } from "./parser";
|
|
2
|
+
import { getPattern } from "./pattern";
|
|
1
3
|
const BASE_URL = "https://tgwidget.github.io/";
|
|
2
4
|
const HEX_RE = /^#?[0-9A-Fa-f]{6}$/;
|
|
3
5
|
const VALID_DATE_MODES = new Set(["date", "time", "datetime", "date-range", "time-range"]);
|
|
@@ -83,6 +85,23 @@ export class TgWidget {
|
|
|
83
85
|
payload() {
|
|
84
86
|
return this._buildPayload();
|
|
85
87
|
}
|
|
88
|
+
get pattern() {
|
|
89
|
+
if (!this._widget)
|
|
90
|
+
throw new Error("No widget type set. Call .date(), .color(), or .schedule() first.");
|
|
91
|
+
return getPattern(this._widget, this._payload);
|
|
92
|
+
}
|
|
93
|
+
parse(value) {
|
|
94
|
+
if (this._widget === "date") {
|
|
95
|
+
return parseDate(value, this._payload);
|
|
96
|
+
}
|
|
97
|
+
if (this._widget === "color") {
|
|
98
|
+
return parseColor(value, this._payload);
|
|
99
|
+
}
|
|
100
|
+
if (this._widget === "schedule") {
|
|
101
|
+
return parseSchedule(value);
|
|
102
|
+
}
|
|
103
|
+
throw new Error("No widget type set. Call .date(), .color(), or .schedule() first.");
|
|
104
|
+
}
|
|
86
105
|
}
|
|
87
106
|
export function tgwidget(botUsername) {
|
|
88
107
|
return new TgWidget(botUsername);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { tgwidget, TgWidget } from "./builder";
|
|
2
2
|
export { parseDate, parseColor, parseSchedule } from "./parser";
|
|
3
|
-
export
|
|
3
|
+
export { getPattern } from "./pattern";
|
|
4
|
+
export type { DateMode, DateFormat, DateOrder, ColorFormat, ColorScheme, WidgetType, WidgetStyle, DateResult, ColorResult, ScheduleDay, ParseResult, } from "./types";
|
package/dist/index.js
CHANGED
package/dist/parser.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
function stripCommand(value) {
|
|
2
|
+
if (value.startsWith("/")) {
|
|
3
|
+
const idx = value.indexOf(" ");
|
|
4
|
+
if (idx !== -1)
|
|
5
|
+
return value.slice(idx + 1);
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
1
9
|
function parseDateStr(value, order) {
|
|
2
10
|
const parts = value.split("-");
|
|
3
11
|
if (order === "ymd")
|
|
@@ -6,7 +14,12 @@ function parseDateStr(value, order) {
|
|
|
6
14
|
return `${parts[2]}-${parts[1]}-${parts[0]}`;
|
|
7
15
|
return `${parts[2]}-${parts[0]}-${parts[1]}`; // mdy
|
|
8
16
|
}
|
|
17
|
+
function dateFromYmd(ymdStr) {
|
|
18
|
+
const [y, m, d] = ymdStr.split("-").map(Number);
|
|
19
|
+
return new Date(y, m - 1, d);
|
|
20
|
+
}
|
|
9
21
|
export function parseDate(value, opts = {}) {
|
|
22
|
+
value = stripCommand(value);
|
|
10
23
|
const { mode = "date", format = "default", order = "ymd" } = opts;
|
|
11
24
|
const result = {};
|
|
12
25
|
if (format === "unix-s" || format === "unix-ms") {
|
|
@@ -15,21 +28,26 @@ export function parseDate(value, opts = {}) {
|
|
|
15
28
|
const ts = parseInt(parts[0], 10);
|
|
16
29
|
result.timestamp = ts;
|
|
17
30
|
const dt = new Date(ts * mul);
|
|
31
|
+
result.dateObj = dt;
|
|
18
32
|
result.date = dt.toISOString().slice(0, 10);
|
|
19
33
|
result.time = dt.toISOString().slice(11, 16);
|
|
20
34
|
if (parts.length > 1) {
|
|
21
35
|
const tsEnd = parseInt(parts[1], 10);
|
|
22
36
|
result.timestampEnd = tsEnd;
|
|
23
37
|
const dtEnd = new Date(tsEnd * mul);
|
|
38
|
+
result.dateEndObj = dtEnd;
|
|
24
39
|
result.dateEnd = dtEnd.toISOString().slice(0, 10);
|
|
25
40
|
result.timeEnd = dtEnd.toISOString().slice(11, 16);
|
|
26
41
|
}
|
|
27
42
|
return result;
|
|
28
43
|
}
|
|
29
44
|
switch (mode) {
|
|
30
|
-
case "date":
|
|
31
|
-
|
|
45
|
+
case "date": {
|
|
46
|
+
const dateStr = parseDateStr(value, order);
|
|
47
|
+
result.date = dateStr;
|
|
48
|
+
result.dateObj = dateFromYmd(dateStr);
|
|
32
49
|
break;
|
|
50
|
+
}
|
|
33
51
|
case "time": {
|
|
34
52
|
const [h, m] = value.split("-");
|
|
35
53
|
result.time = `${h}:${m}`;
|
|
@@ -37,15 +55,23 @@ export function parseDate(value, opts = {}) {
|
|
|
37
55
|
}
|
|
38
56
|
case "datetime": {
|
|
39
57
|
const [datePart, timePart] = value.split("_");
|
|
40
|
-
|
|
58
|
+
const dateStr = parseDateStr(datePart, order);
|
|
41
59
|
const [h, m] = timePart.split("-");
|
|
60
|
+
result.date = dateStr;
|
|
42
61
|
result.time = `${h}:${m}`;
|
|
62
|
+
const d = dateFromYmd(dateStr);
|
|
63
|
+
d.setHours(parseInt(h, 10), parseInt(m, 10), 0, 0);
|
|
64
|
+
result.dateObj = d;
|
|
43
65
|
break;
|
|
44
66
|
}
|
|
45
67
|
case "date-range": {
|
|
46
68
|
const parts = value.split("_");
|
|
47
|
-
|
|
48
|
-
|
|
69
|
+
const dateStr = parseDateStr(parts[0], order);
|
|
70
|
+
const dateEndStr = parseDateStr(parts[1], order);
|
|
71
|
+
result.date = dateStr;
|
|
72
|
+
result.dateEnd = dateEndStr;
|
|
73
|
+
result.dateObj = dateFromYmd(dateStr);
|
|
74
|
+
result.dateEndObj = dateFromYmd(dateEndStr);
|
|
49
75
|
break;
|
|
50
76
|
}
|
|
51
77
|
case "time-range": {
|
|
@@ -60,6 +86,7 @@ export function parseDate(value, opts = {}) {
|
|
|
60
86
|
return result;
|
|
61
87
|
}
|
|
62
88
|
export function parseColor(value, opts = {}) {
|
|
89
|
+
value = stripCommand(value);
|
|
63
90
|
const { format = "hex" } = opts;
|
|
64
91
|
const result = { raw: value };
|
|
65
92
|
if (format === "hex") {
|
|
@@ -76,6 +103,7 @@ export function parseColor(value, opts = {}) {
|
|
|
76
103
|
return result;
|
|
77
104
|
}
|
|
78
105
|
export function parseSchedule(value) {
|
|
106
|
+
value = stripCommand(value);
|
|
79
107
|
if (value.length !== 56) {
|
|
80
108
|
throw new Error(`Schedule bunch format must be 56 chars, got ${value.length}`);
|
|
81
109
|
}
|
package/dist/pattern.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const DATE_PATTERNS = {
|
|
2
|
+
ymd: "YYYY-MM-DD",
|
|
3
|
+
dmy: "DD-MM-YYYY",
|
|
4
|
+
mdy: "MM-DD-YYYY",
|
|
5
|
+
};
|
|
6
|
+
const TIME_PATTERN = "HH-MM";
|
|
7
|
+
export function getPattern(widget, payload) {
|
|
8
|
+
if (widget === "date") {
|
|
9
|
+
const mode = payload.mode ?? "date";
|
|
10
|
+
const order = payload.order ?? "ymd";
|
|
11
|
+
const datePat = DATE_PATTERNS[order];
|
|
12
|
+
switch (mode) {
|
|
13
|
+
case "date":
|
|
14
|
+
return datePat;
|
|
15
|
+
case "time":
|
|
16
|
+
return TIME_PATTERN;
|
|
17
|
+
case "datetime":
|
|
18
|
+
return `${datePat}_${TIME_PATTERN}`;
|
|
19
|
+
case "date-range":
|
|
20
|
+
return `${datePat}_${datePat}`;
|
|
21
|
+
case "time-range":
|
|
22
|
+
return `${TIME_PATTERN}_${TIME_PATTERN}`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (widget === "color") {
|
|
26
|
+
const format = payload.format ?? "hex";
|
|
27
|
+
switch (format) {
|
|
28
|
+
case "hex":
|
|
29
|
+
return "#RRGGBB";
|
|
30
|
+
case "rgb":
|
|
31
|
+
return "R, G, B";
|
|
32
|
+
case "hsl":
|
|
33
|
+
return "H, S, L";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (widget === "schedule") {
|
|
37
|
+
return "HH:MM—HH:MM × 7 days";
|
|
38
|
+
}
|
|
39
|
+
return "";
|
|
40
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export type DateFormat = "default" | "unix-s" | "unix-ms";
|
|
|
3
3
|
export type DateOrder = "ymd" | "dmy" | "mdy";
|
|
4
4
|
export type ColorFormat = "hex" | "rgb" | "hsl";
|
|
5
5
|
export type ColorScheme = "light" | "dark" | "auto";
|
|
6
|
+
export type WidgetType = "date" | "color" | "schedule";
|
|
6
7
|
export interface WidgetStyle {
|
|
7
8
|
colorScheme?: ColorScheme;
|
|
8
9
|
accent?: string;
|
|
@@ -18,6 +19,8 @@ export interface DateResult {
|
|
|
18
19
|
timeEnd?: string;
|
|
19
20
|
timestamp?: number;
|
|
20
21
|
timestampEnd?: number;
|
|
22
|
+
dateObj?: Date;
|
|
23
|
+
dateEndObj?: Date;
|
|
21
24
|
}
|
|
22
25
|
export interface ColorResult {
|
|
23
26
|
raw: string;
|
|
@@ -30,3 +33,4 @@ export interface ScheduleDay {
|
|
|
30
33
|
start?: string;
|
|
31
34
|
end?: string;
|
|
32
35
|
}
|
|
36
|
+
export type ParseResult<T extends WidgetType | null> = T extends "date" ? DateResult : T extends "color" ? ColorResult : T extends "schedule" ? ScheduleDay[] : DateResult | ColorResult | ScheduleDay[];
|