hermesbuttons 1.0.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.
- package/LICENSE +21 -0
- package/README.md +397 -0
- package/dist/chunk-3CPSZAJ2.mjs +398 -0
- package/dist/chunk-3CPSZAJ2.mjs.map +1 -0
- package/dist/hermes-button-OWZRXNSO.mjs +263 -0
- package/dist/hermes-button-OWZRXNSO.mjs.map +1 -0
- package/dist/hermes-skill-button-5MLIQS4T.mjs +263 -0
- package/dist/hermes-skill-button-5MLIQS4T.mjs.map +1 -0
- package/dist/index.d.mts +245 -0
- package/dist/index.d.ts +245 -0
- package/dist/index.global.js +920 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +921 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +921 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +84 -0
- package/dist/react.d.ts +84 -0
- package/dist/react.js +920 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +2 -0
- package/dist/react.mjs.map +1 -0
- package/dist/vue.d.mts +64 -0
- package/dist/vue.d.ts +64 -0
- package/dist/vue.js +920 -0
- package/dist/vue.js.map +1 -0
- package/dist/vue.mjs +920 -0
- package/dist/vue.mjs.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hermesbuttons contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# hermesbuttons
|
|
2
|
+
|
|
3
|
+
Drop-in **"Run on Hermes"** and **"Run on Hermes Skills"** buttons for any website or framework. Built as framework-agnostic Web Components with zero dependencies.
|
|
4
|
+
|
|
5
|
+
**Hermes button** (`<hermes-button>`) copies a full CLI invocation using `hermes -p "..."` so users can paste into a terminal. **Hermes skill button** (`<hermes-skill-button>`) guides skill installation and ties into Hermes Agent workflows with persistent memory.
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="https://img.shields.io/npm/v/hermesbuttons?color=%237C3AED&label=npm" alt="npm version">
|
|
9
|
+
<img src="https://img.shields.io/bundlephobia/minzip/hermesbuttons?color=%237C3AED" alt="bundle size">
|
|
10
|
+
<img src="https://img.shields.io/npm/l/hermesbuttons?color=%237C3AED" alt="license">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install hermesbuttons
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Or use the CDN** (no build step):
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<script src="https://unpkg.com/hermesbuttons"></script>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<hermes-button command="/research deep-dive on React Server Components" theme="branded"></hermes-button>
|
|
33
|
+
<hermes-skill-button
|
|
34
|
+
command="/competitive-analysis"
|
|
35
|
+
skill-url="https://example.com/skills/competitive-analysis.zip"
|
|
36
|
+
></hermes-skill-button>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Framework Integration
|
|
42
|
+
|
|
43
|
+
### Vanilla HTML / CDN
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<script src="https://unpkg.com/hermesbuttons"></script>
|
|
47
|
+
|
|
48
|
+
<hermes-button command="/weekly-standup" theme="branded"></hermes-button>
|
|
49
|
+
<hermes-skill-button command="/draft-blog-post" theme="dark"></hermes-skill-button>
|
|
50
|
+
|
|
51
|
+
<script>
|
|
52
|
+
document.querySelector('hermes-button')
|
|
53
|
+
.addEventListener('hb-copy', (e) => console.log('Copied:', e.detail.command));
|
|
54
|
+
</script>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### React / Next.js
|
|
58
|
+
|
|
59
|
+
Use the dedicated React wrappers (handles SSR, hydration, and prop forwarding):
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { HermesButton, HermesSkillButton } from 'hermesbuttons/react';
|
|
63
|
+
|
|
64
|
+
function App() {
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<HermesButton
|
|
68
|
+
command="/research deep-dive on React Server Components"
|
|
69
|
+
theme="branded"
|
|
70
|
+
onCopy={(cmd) => console.log('Copied:', cmd)}
|
|
71
|
+
onHbCopy={(e) => console.log('Event:', e.detail.command)}
|
|
72
|
+
/>
|
|
73
|
+
<HermesSkillButton
|
|
74
|
+
command="/competitive-analysis"
|
|
75
|
+
skillUrl="https://example.com/skills/competitive-analysis.zip"
|
|
76
|
+
theme="dark"
|
|
77
|
+
/>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The React wrapper:
|
|
84
|
+
|
|
85
|
+
- Includes `'use client'` for Next.js App Router
|
|
86
|
+
- Handles SSR/hydration with `suppressHydrationWarning`
|
|
87
|
+
- Lazy-loads the Web Components to avoid SSR crashes
|
|
88
|
+
- Forwards both property callbacks (`onCopy`, `onDownload`) and CustomEvent listeners (`onHbCopy`, `onHbDownload`, etc.)
|
|
89
|
+
|
|
90
|
+
### Vue / Nuxt
|
|
91
|
+
|
|
92
|
+
**Option A: Vue Plugin (recommended)**
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// main.ts
|
|
96
|
+
import { createApp } from 'vue';
|
|
97
|
+
import { HermesButtonsPlugin } from 'hermesbuttons/vue';
|
|
98
|
+
import App from './App.vue';
|
|
99
|
+
|
|
100
|
+
const app = createApp(App);
|
|
101
|
+
app.use(HermesButtonsPlugin); // auto-configures isCustomElement
|
|
102
|
+
app.mount('#app');
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<template>
|
|
107
|
+
<hermes-button
|
|
108
|
+
command="/weekly-standup"
|
|
109
|
+
theme="branded"
|
|
110
|
+
@hb-copy="onCopy"
|
|
111
|
+
/>
|
|
112
|
+
<hermes-skill-button
|
|
113
|
+
command="/draft-blog-post"
|
|
114
|
+
theme="dark"
|
|
115
|
+
@hb-download="onDownload"
|
|
116
|
+
/>
|
|
117
|
+
</template>
|
|
118
|
+
|
|
119
|
+
<script setup>
|
|
120
|
+
function onCopy(e) {
|
|
121
|
+
console.log('Copied:', e.detail.command);
|
|
122
|
+
}
|
|
123
|
+
function onDownload(e) {
|
|
124
|
+
console.log('Downloaded:', e.detail.url);
|
|
125
|
+
}
|
|
126
|
+
</script>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Option B: Manual setup**
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
// vite.config.ts
|
|
133
|
+
import vue from '@vitejs/plugin-vue';
|
|
134
|
+
|
|
135
|
+
export default {
|
|
136
|
+
plugins: [
|
|
137
|
+
vue({
|
|
138
|
+
template: {
|
|
139
|
+
compilerOptions: {
|
|
140
|
+
isCustomElement: (tag) =>
|
|
141
|
+
['hermes-button', 'hermes-skill-button', 'hermes-popup-dialog'].includes(tag),
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```vue
|
|
150
|
+
<script setup>
|
|
151
|
+
import 'hermesbuttons';
|
|
152
|
+
</script>
|
|
153
|
+
|
|
154
|
+
<template>
|
|
155
|
+
<hermes-button command="/weekly-standup" theme="branded" @hb-copy="onCopy" />
|
|
156
|
+
</template>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Svelte / SvelteKit
|
|
160
|
+
|
|
161
|
+
```svelte
|
|
162
|
+
<script>
|
|
163
|
+
import 'hermesbuttons';
|
|
164
|
+
|
|
165
|
+
function handleCopy(e) {
|
|
166
|
+
console.log('Copied:', e.detail.command);
|
|
167
|
+
}
|
|
168
|
+
</script>
|
|
169
|
+
|
|
170
|
+
<hermes-button
|
|
171
|
+
command="/research deep-dive on React Server Components"
|
|
172
|
+
theme="branded"
|
|
173
|
+
on:hb-copy={handleCopy}
|
|
174
|
+
/>
|
|
175
|
+
<hermes-skill-button command="/competitive-analysis" theme="dark" />
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Angular
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// app.module.ts
|
|
182
|
+
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
|
183
|
+
import 'hermesbuttons';
|
|
184
|
+
|
|
185
|
+
@NgModule({
|
|
186
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
187
|
+
// ...
|
|
188
|
+
})
|
|
189
|
+
export class AppModule {}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```html
|
|
193
|
+
<!-- component.html -->
|
|
194
|
+
<hermes-button
|
|
195
|
+
command="/weekly-standup"
|
|
196
|
+
theme="branded"
|
|
197
|
+
(hb-copy)="onCopy($event)"
|
|
198
|
+
></hermes-button>
|
|
199
|
+
|
|
200
|
+
<hermes-skill-button
|
|
201
|
+
command="/draft-blog-post"
|
|
202
|
+
skill-url="https://example.com/skills/draft-blog.zip"
|
|
203
|
+
theme="dark"
|
|
204
|
+
(hb-download)="onDownload($event)"
|
|
205
|
+
></hermes-skill-button>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Solid
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import 'hermesbuttons';
|
|
212
|
+
|
|
213
|
+
function App() {
|
|
214
|
+
return (
|
|
215
|
+
<>
|
|
216
|
+
<hermes-button
|
|
217
|
+
command="/research deep-dive on React Server Components"
|
|
218
|
+
theme="branded"
|
|
219
|
+
on:hb-copy={(e) => console.log(e.detail.command)}
|
|
220
|
+
/>
|
|
221
|
+
<hermes-skill-button command="/competitive-analysis" theme="dark" />
|
|
222
|
+
</>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Astro
|
|
228
|
+
|
|
229
|
+
```astro
|
|
230
|
+
---
|
|
231
|
+
---
|
|
232
|
+
<script>
|
|
233
|
+
import 'hermesbuttons';
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<hermes-button command="/weekly-standup" theme="branded" />
|
|
237
|
+
<hermes-skill-button command="/draft-blog-post" theme="dark" />
|
|
238
|
+
|
|
239
|
+
<script>
|
|
240
|
+
document.querySelector('hermes-button')
|
|
241
|
+
?.addEventListener('hb-copy', (e) => console.log(e.detail.command));
|
|
242
|
+
</script>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Programmatic JavaScript API
|
|
246
|
+
|
|
247
|
+
```js
|
|
248
|
+
import { createHermesButton, createHermesSkillButton } from 'hermesbuttons';
|
|
249
|
+
|
|
250
|
+
const btn = createHermesButton({
|
|
251
|
+
command: '/competitive-analysis',
|
|
252
|
+
theme: 'branded',
|
|
253
|
+
onCopy: (cmd) => console.log('Copied:', cmd),
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
document.getElementById('container').appendChild(btn);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
When using the global build:
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
const btn = HermesButtons.createHermesButton({ command: '/weekly-standup', theme: 'branded' });
|
|
263
|
+
document.body.appendChild(btn);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Themes
|
|
269
|
+
|
|
270
|
+
| Theme | Description |
|
|
271
|
+
|-------|-------------|
|
|
272
|
+
| `branded` | Violet primary (`#7C3AED`), white text **(default)** |
|
|
273
|
+
| `branded-alt` | Teal primary (`#14B8A6`), white text — secondary accent |
|
|
274
|
+
| `dark` | Dark surface, light text, violet accents |
|
|
275
|
+
| `light` | Light surface, dark text, violet accents |
|
|
276
|
+
| `system` | Auto-switches between `light`/`dark` based on `prefers-color-scheme` |
|
|
277
|
+
|
|
278
|
+
## Sizes
|
|
279
|
+
|
|
280
|
+
| Size | Height |
|
|
281
|
+
|------|--------|
|
|
282
|
+
| `sm` | 2rem (32px at default font size) |
|
|
283
|
+
| `md` | 2.5rem (40px) **(default)** |
|
|
284
|
+
| `lg` | 3rem (48px) |
|
|
285
|
+
|
|
286
|
+
Sizes use `rem` units and scale with the user's browser font preferences.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Events
|
|
291
|
+
|
|
292
|
+
All buttons dispatch native `CustomEvent`s with `bubbles: true` and `composed: true` (crosses Shadow DOM).
|
|
293
|
+
|
|
294
|
+
| Event | Detail | Fired when |
|
|
295
|
+
|-------|--------|------------|
|
|
296
|
+
| `hb-copy` | `{ command: string }` | Command copied to clipboard |
|
|
297
|
+
| `hb-open` | `{ command: string }` | Button clicked / popup opens |
|
|
298
|
+
| `hb-close` | — | Popup closed |
|
|
299
|
+
| `hb-download` | `{ url: string }` | Skill package downloaded (Hermes skill button only) |
|
|
300
|
+
|
|
301
|
+
```js
|
|
302
|
+
el.addEventListener('hb-copy', (e) => {
|
|
303
|
+
console.log('Copied:', e.detail.command);
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## API Reference
|
|
310
|
+
|
|
311
|
+
### `<hermes-button>` Attributes
|
|
312
|
+
|
|
313
|
+
| Attribute | Type | Default | Description |
|
|
314
|
+
|-----------|------|---------|-------------|
|
|
315
|
+
| `command` | `string` | — | The prompt/command to run |
|
|
316
|
+
| `theme` | `'branded' \| 'branded-alt' \| 'dark' \| 'light' \| 'system'` | `'branded'` | Theme variant |
|
|
317
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
|
|
318
|
+
| `variant` | `'filled' \| 'outline' \| 'ghost'` | `'filled'` | Visual style |
|
|
319
|
+
| `shape` | `'rounded' \| 'pill' \| 'square'` | `'rounded'` | Border radius |
|
|
320
|
+
| `popup` | `'true' \| 'false'` | `'true'` | Show popup dialog on click |
|
|
321
|
+
| `prompt-flag` | `'true' \| 'false'` | `'true'` | Prepend `hermes -p` to the command |
|
|
322
|
+
| `popup-title` | `string` | `'Run on Hermes'` | Custom popup title |
|
|
323
|
+
| `popup-description` | `string` | — | Custom popup description |
|
|
324
|
+
|
|
325
|
+
### `<hermes-skill-button>` Attributes
|
|
326
|
+
|
|
327
|
+
| Attribute | Type | Default | Description |
|
|
328
|
+
|-----------|------|---------|-------------|
|
|
329
|
+
| `command` | `string` | — | The slash command to run |
|
|
330
|
+
| `skill-url` | `string` | — | URL to downloadable skill package |
|
|
331
|
+
| `theme` | `'branded' \| 'branded-alt' \| 'dark' \| 'light' \| 'system'` | `'branded'` | Theme variant |
|
|
332
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
|
|
333
|
+
| `variant` | `'filled' \| 'outline' \| 'ghost'` | `'filled'` | Visual style |
|
|
334
|
+
| `shape` | `'rounded' \| 'pill' \| 'square'` | `'rounded'` | Border radius |
|
|
335
|
+
| `popup` | `'true' \| 'false'` | `'true'` | Show popup dialog on click |
|
|
336
|
+
| `popup-title` | `string` | `'Run on Hermes Skills'` | Custom popup title |
|
|
337
|
+
| `popup-description` | `string` | — | Custom popup description |
|
|
338
|
+
|
|
339
|
+
### JavaScript Exports
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
// Web Components + factories
|
|
343
|
+
import {
|
|
344
|
+
HermesButton, // Web Component class
|
|
345
|
+
HermesSkillButton, // Web Component class
|
|
346
|
+
createHermesButton, // Factory function
|
|
347
|
+
createHermesSkillButton,// Factory function
|
|
348
|
+
showPopup, // Show popup programmatically
|
|
349
|
+
register, // Manually register all custom elements
|
|
350
|
+
registerHermesButton, // Register only hermes-button
|
|
351
|
+
registerHermesSkillButton, // Register only hermes-skill-button
|
|
352
|
+
} from 'hermesbuttons';
|
|
353
|
+
|
|
354
|
+
// React wrappers (SSR-safe, includes 'use client')
|
|
355
|
+
import { HermesButton, HermesSkillButton } from 'hermesbuttons/react';
|
|
356
|
+
|
|
357
|
+
// Vue plugin
|
|
358
|
+
import { HermesButtonsPlugin } from 'hermesbuttons/vue';
|
|
359
|
+
|
|
360
|
+
// Raw SVG icons + theme tokens
|
|
361
|
+
import { HERMES_ICON, HERMES_SKILL_ICON, BRAND_COLOR, ALT_BRAND_COLOR } from 'hermesbuttons';
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Explicit Registration
|
|
365
|
+
|
|
366
|
+
Registration happens automatically on import. For frameworks that need timing control:
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
import { register } from 'hermesbuttons';
|
|
370
|
+
|
|
371
|
+
// Call when you're ready to register the custom elements
|
|
372
|
+
register();
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Or register individually with custom tag names:
|
|
376
|
+
|
|
377
|
+
```ts
|
|
378
|
+
import { registerHermesButton, registerHermesSkillButton } from 'hermesbuttons';
|
|
379
|
+
|
|
380
|
+
registerHermesButton('my-hermes-btn');
|
|
381
|
+
registerHermesSkillButton('my-hermes-skill-btn');
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Browser Support
|
|
387
|
+
|
|
388
|
+
Works in all browsers that support [Custom Elements v1](https://caniuse.com/custom-elementsv1):
|
|
389
|
+
|
|
390
|
+
- Chrome 67+
|
|
391
|
+
- Firefox 63+
|
|
392
|
+
- Safari 10.1+
|
|
393
|
+
- Edge 79+
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
MIT
|