hotsheet 0.15.0 → 0.15.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hotsheet",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
4
4
  "description": "A lightweight local project management tool. Create, categorize, and prioritize tickets with a fast bullet-list interface, then export an Up Next worklist for AI tools.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,189 +0,0 @@
1
- // plugins/demo-plugin/src/index.ts
2
- var context;
3
- var BOLT_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>';
4
- var INFO_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>';
5
- var BELL_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>';
6
- async function activate(ctx) {
7
- context = ctx;
8
- const username = await ctx.getSetting("username");
9
- ctx.registerUI([
10
- // --- Buttons (all locations + styles) ---
11
- // Toolbar: default style
12
- {
13
- id: "demo-toolbar",
14
- type: "button",
15
- location: "toolbar",
16
- icon: BOLT_ICON,
17
- title: "Demo Plugin Action",
18
- action: "toolbar_click"
19
- },
20
- // Status bar
21
- {
22
- id: "demo-status",
23
- type: "button",
24
- location: "status_bar",
25
- label: username ? `Demo: ${username}` : "Demo Plugin",
26
- title: "Demo status bar button",
27
- action: "status_click"
28
- },
29
- // Detail panel — top (above fields)
30
- {
31
- id: "demo-detail-top",
32
- type: "button",
33
- location: "detail_top",
34
- icon: INFO_ICON,
35
- label: "Ticket Info",
36
- title: "Demo detail top button",
37
- action: "detail_top_click"
38
- },
39
- // Detail panel — bottom (below notes), primary style
40
- {
41
- id: "demo-detail-bottom",
42
- type: "button",
43
- location: "detail_bottom",
44
- icon: BELL_ICON,
45
- label: "Notify",
46
- title: "Demo detail bottom button (primary style)",
47
- style: "primary",
48
- action: "detail_bottom_click"
49
- },
50
- // Context menu
51
- {
52
- id: "demo-context",
53
- type: "button",
54
- location: "context_menu",
55
- icon: BOLT_ICON,
56
- label: "Demo Action",
57
- title: "Demo context menu item",
58
- action: "context_click"
59
- },
60
- // Batch menu (shown when multiple tickets selected → "..." menu)
61
- {
62
- id: "demo-batch",
63
- type: "button",
64
- location: "batch_menu",
65
- icon: BOLT_ICON,
66
- label: "Demo Batch Action",
67
- title: "Demo batch menu item",
68
- action: "batch_click"
69
- },
70
- // --- Sidebar ---
71
- // Sidebar top (before views)
72
- {
73
- id: "demo-sidebar-top",
74
- type: "button",
75
- location: "sidebar_actions_top",
76
- icon: BOLT_ICON,
77
- label: "Demo Sidebar",
78
- title: "Demo sidebar top button",
79
- action: "sidebar_top_click"
80
- },
81
- // Sidebar bottom (after views)
82
- {
83
- id: "demo-sidebar-bottom",
84
- type: "button",
85
- location: "sidebar_actions_bottom",
86
- icon: INFO_ICON,
87
- label: "Demo Bottom",
88
- title: "Demo sidebar bottom button",
89
- action: "sidebar_bottom_click"
90
- },
91
- // --- Link ---
92
- {
93
- id: "demo-link",
94
- type: "link",
95
- location: "detail_bottom",
96
- url: "https://github.com",
97
- label: "GitHub",
98
- icon: INFO_ICON,
99
- title: "Demo external link"
100
- }
101
- ]);
102
- ctx.log("info", `Demo plugin activated${username ? ` for ${username}` : ""}`);
103
- }
104
- async function onAction(actionId, _actionContext) {
105
- if (actionId === "test_connection") {
106
- const apiKey = await context.getSetting("api_key");
107
- const username = await context.getSetting("username");
108
- if (!apiKey || !username) {
109
- context.updateConfigLabel("connection-status", "Missing required fields", "warning");
110
- return { connected: false, error: "Missing api_key or username" };
111
- }
112
- await new Promise((r) => setTimeout(r, 500));
113
- if (apiKey.length < 8) {
114
- context.updateConfigLabel("connection-status", "Invalid API key (too short)", "error");
115
- return { connected: false, error: "API key too short" };
116
- }
117
- context.updateConfigLabel("connection-status", `Connected as ${username}`, "success");
118
- return { connected: true };
119
- }
120
- if (actionId === "toolbar_click") {
121
- context.log("info", "Toolbar button clicked");
122
- return { message: "Toolbar action executed" };
123
- }
124
- if (actionId === "status_click") {
125
- context.log("info", "Status bar button clicked");
126
- return { message: "Status bar action executed" };
127
- }
128
- if (actionId === "detail_top_click") {
129
- const ticketIds = _actionContext.ticketIds ?? [];
130
- context.log("info", `Detail top button clicked for tickets: ${ticketIds.join(", ")}`);
131
- return { message: `Info for ${ticketIds.length} ticket(s)` };
132
- }
133
- if (actionId === "detail_bottom_click") {
134
- const ticketIds = _actionContext.ticketIds ?? [];
135
- context.log("info", `Detail bottom (notify) clicked for tickets: ${ticketIds.join(", ")}`);
136
- return { message: `Notified for ${ticketIds.length} ticket(s)` };
137
- }
138
- if (actionId === "context_click") {
139
- const ticketIds = _actionContext.ticketIds ?? [];
140
- context.log("info", `Context menu action for tickets: ${ticketIds.join(", ")}`);
141
- return { message: `Context action on ${ticketIds.length} ticket(s)` };
142
- }
143
- if (actionId === "sidebar_top_click") {
144
- context.log("info", "Sidebar top button clicked");
145
- return { message: "Sidebar action executed" };
146
- }
147
- if (actionId === "batch_click") {
148
- const ticketIds = _actionContext.ticketIds ?? [];
149
- context.log("info", `Batch action for tickets: ${ticketIds.join(", ")}`);
150
- return { message: `Batch action on ${ticketIds.length} ticket(s)` };
151
- }
152
- return null;
153
- }
154
- async function validateField(key, value) {
155
- if (key === "api_key") {
156
- if (!value) return { status: "error", message: "Required" };
157
- if (value.length < 8) return { status: "warning", message: "Key should be at least 8 characters" };
158
- return { status: "success", message: "Valid API key format" };
159
- }
160
- if (key === "username") {
161
- if (!value) return { status: "error", message: "Required" };
162
- if (/\s/.test(value)) return { status: "error", message: "Cannot contain spaces" };
163
- if (value.length < 3) return { status: "warning", message: "Username is very short" };
164
- return { status: "success", message: `Hello, ${value}!` };
165
- }
166
- if (key === "webhook_url") {
167
- if (!value) return null;
168
- try {
169
- const url = new URL(value);
170
- if (url.protocol !== "https:") return { status: "warning", message: "HTTPS recommended" };
171
- return { status: "success", message: "Valid URL" };
172
- } catch {
173
- return { status: "error", message: "Invalid URL format" };
174
- }
175
- }
176
- if (key === "max_items") {
177
- const n = parseInt(value, 10);
178
- if (isNaN(n)) return { status: "error", message: "Must be a number" };
179
- if (n < 1) return { status: "error", message: "Must be at least 1" };
180
- if (n > 1e3) return { status: "warning", message: "Large values may be slow" };
181
- return null;
182
- }
183
- return null;
184
- }
185
- export {
186
- activate,
187
- onAction,
188
- validateField
189
- };
@@ -1,106 +0,0 @@
1
- {
2
- "id": "demo-plugin",
3
- "name": "Demo Plugin",
4
- "version": "1.0.0",
5
- "description": "Demonstrates all plugin features — settings UI types, config layout, UI extensions, label colors, and field validation. For local development and testing only.",
6
- "author": "Hot Sheet",
7
- "entry": "index.js",
8
- "icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>",
9
- "preferences": [
10
- {
11
- "key": "api_key",
12
- "label": "API Key",
13
- "type": "string",
14
- "required": true,
15
- "secret": true,
16
- "scope": "global",
17
- "description": "A secret API key (demonstrates global-scoped secret fields)"
18
- },
19
- {
20
- "key": "username",
21
- "label": "Username",
22
- "type": "string",
23
- "required": true,
24
- "description": "Your username (demonstrates required string validation)"
25
- },
26
- {
27
- "key": "auto_greet",
28
- "label": "Auto-greet on sync",
29
- "type": "boolean",
30
- "default": true,
31
- "description": "Show a greeting when sync runs (demonstrates boolean toggle)"
32
- },
33
- {
34
- "key": "max_items",
35
- "label": "Max Items",
36
- "type": "number",
37
- "default": 10,
38
- "description": "Maximum number of items to process (demonstrates number input)"
39
- },
40
- {
41
- "key": "theme",
42
- "label": "Color Theme",
43
- "type": "select",
44
- "default": "blue",
45
- "options": [
46
- { "value": "blue", "label": "Ocean Blue" },
47
- { "value": "green", "label": "Forest Green" },
48
- { "value": "purple", "label": "Cosmic Purple" },
49
- { "value": "orange", "label": "Sunset Orange" }
50
- ],
51
- "description": "Visual theme (demonstrates select/dropdown)"
52
- },
53
- {
54
- "key": "region",
55
- "label": "Region",
56
- "type": "combo",
57
- "default": "us-east",
58
- "options": [
59
- { "value": "us-east", "label": "US East" },
60
- { "value": "us-west", "label": "US West" },
61
- { "value": "eu-west", "label": "EU West" },
62
- { "value": "ap-south", "label": "Asia Pacific" }
63
- ],
64
- "description": "Server region — pick from list or type a custom value (demonstrates combo box)"
65
- },
66
- {
67
- "key": "sync_mode",
68
- "label": "Sync Mode",
69
- "type": "dropdown",
70
- "default": "auto",
71
- "options": [
72
- { "value": "auto", "label": "Automatic" },
73
- { "value": "manual", "label": "Manual Only" },
74
- { "value": "scheduled", "label": "Scheduled" }
75
- ],
76
- "description": "When to sync (demonstrates dropdown, alias for select)"
77
- },
78
- {
79
- "key": "webhook_url",
80
- "label": "Webhook URL",
81
- "type": "string",
82
- "default": "",
83
- "description": "Optional callback URL (demonstrates non-required string with URL validation)"
84
- }
85
- ],
86
- "configLayout": [
87
- { "type": "preference", "key": "api_key" },
88
- { "type": "divider" },
89
- { "type": "preference", "key": "username" },
90
- { "type": "preference", "key": "auto_greet" },
91
- { "type": "spacer" },
92
- { "type": "label", "id": "connection-status", "text": "Not tested", "color": "transient" },
93
- { "type": "button", "id": "test-btn", "label": "Test Connection", "action": "test_connection" },
94
- { "type": "group", "title": "Appearance", "collapsed": false, "items": [
95
- { "type": "preference", "key": "theme" },
96
- { "type": "preference", "key": "max_items" }
97
- ]},
98
- { "type": "group", "title": "Sync Settings", "collapsed": true, "items": [
99
- { "type": "preference", "key": "sync_mode" },
100
- { "type": "preference", "key": "region" }
101
- ]},
102
- { "type": "group", "title": "Advanced", "collapsed": true, "items": [
103
- { "type": "preference", "key": "webhook_url" }
104
- ]}
105
- ]
106
- }