@herdingbits/trailhead-shoelace 0.0.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/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # @herdingbits/trailhead-shoelace
2
+
3
+ Shoelace design system adapter for the Trailhead micro-frontend framework.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @herdingbits/trailhead-core @herdingbits/trailhead-shoelace @shoelace-style/shoelace
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { Trailhead } from '@herdingbits/trailhead-core';
15
+ import { ShoelaceAdapter, ShellApp } from '@herdingbits/trailhead-shoelace';
16
+ import '@herdingbits/trailhead-shoelace/shell.css';
17
+
18
+ const shell = new Trailhead({
19
+ adapter: new ShoelaceAdapter(),
20
+ basePath: '/app',
21
+ apiUrl: 'https://api.example.com'
22
+ });
23
+
24
+ ShellApp.mount(shell);
25
+ ```
26
+
27
+ ## Documentation
28
+
29
+ See the [main Trailhead documentation](https://github.com/herdingbits/trailhead) for more information.
30
+
31
+ ## License
32
+
33
+ MIT
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shoelace Design System Adapter
3
+ */
4
+ import type { DesignSystemAdapter, FeedbackAdapter } from '@herdingbits/trailhead-types/adapters';
5
+ export declare class ShoelaceAdapter implements DesignSystemAdapter {
6
+ name: string;
7
+ version: string;
8
+ feedback: FeedbackAdapter;
9
+ constructor();
10
+ init(basePath: string): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAA4C,MAAM,uCAAuC,CAAC;AA2F5I,qBAAa,eAAgB,YAAW,mBAAmB;IACzD,IAAI,SAAc;IAClB,OAAO,SAAW;IAClB,QAAQ,EAAE,eAAe,CAAC;;IAMpB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAW5C"}
@@ -0,0 +1,96 @@
1
+ class ShoelaceFeedbackAdapter {
2
+ constructor() {
3
+ this.busyOverlay = null;
4
+ this.toastContainer = null;
5
+ }
6
+ showBusy(message) {
7
+ if (!this.busyOverlay) {
8
+ this.busyOverlay = document.createElement("div");
9
+ this.busyOverlay.id = "shell-busy-overlay";
10
+ this.busyOverlay.innerHTML = `
11
+ <div class="shell-busy-content">
12
+ <div class="shell-spinner"></div>
13
+ <div class="shell-busy-message"></div>
14
+ </div>
15
+ `;
16
+ document.body.appendChild(this.busyOverlay);
17
+ }
18
+ const messageEl = this.busyOverlay.querySelector(".shell-busy-message");
19
+ if (messageEl) {
20
+ messageEl.textContent = message;
21
+ }
22
+ this.busyOverlay.style.display = "flex";
23
+ }
24
+ clearBusy() {
25
+ if (this.busyOverlay) {
26
+ this.busyOverlay.style.display = "none";
27
+ }
28
+ }
29
+ showToast(message, variant, duration = 3000) {
30
+ if (!this.toastContainer) {
31
+ this.toastContainer = document.createElement("div");
32
+ this.toastContainer.id = "shell-toast-container";
33
+ document.body.appendChild(this.toastContainer);
34
+ }
35
+ const toast = document.createElement("div");
36
+ toast.className = `shell-toast shell-toast-${variant}`;
37
+ toast.textContent = message;
38
+ this.toastContainer.appendChild(toast);
39
+ setTimeout(() => toast.classList.add("shell-toast-show"), 10);
40
+ setTimeout(() => {
41
+ toast.classList.remove("shell-toast-show");
42
+ setTimeout(() => toast.remove(), 300);
43
+ }, duration);
44
+ }
45
+ showDialog(config) {
46
+ return new Promise((resolve) => {
47
+ const dialog = document.createElement("div");
48
+ dialog.className = "shell-dialog-overlay";
49
+ dialog.innerHTML = `
50
+ <div class="shell-dialog">
51
+ ${config.title ? `<div class="shell-dialog-title">${config.title}</div>` : ''}
52
+ <div class="shell-dialog-message">${config.message}</div>
53
+ <div class="shell-dialog-buttons">
54
+ ${config.buttons
55
+ .map((btn) => `<button class="shell-btn shell-btn-${btn.variant || "default"}" data-value="${btn.value}">${btn.label}</button>`)
56
+ .join("")}
57
+ </div>
58
+ </div>
59
+ `;
60
+ dialog.querySelectorAll("button").forEach((btn) => {
61
+ btn.onclick = () => {
62
+ const value = btn.getAttribute("data-value");
63
+ dialog.remove();
64
+ resolve({ value });
65
+ };
66
+ });
67
+ // Click outside to cancel
68
+ dialog.onclick = (e) => {
69
+ if (e.target === dialog) {
70
+ dialog.remove();
71
+ resolve({ value: null });
72
+ }
73
+ };
74
+ document.body.appendChild(dialog);
75
+ });
76
+ }
77
+ }
78
+ export class ShoelaceAdapter {
79
+ constructor() {
80
+ this.name = "shoelace";
81
+ this.version = "1.0.0";
82
+ this.feedback = new ShoelaceFeedbackAdapter();
83
+ }
84
+ async init(basePath) {
85
+ try {
86
+ const shoelacePath = `${basePath}/shoelace`;
87
+ const { setBasePath } = await import(/* @vite-ignore */ `${shoelacePath}/utilities/base-path.js`);
88
+ setBasePath(shoelacePath);
89
+ await import(/* @vite-ignore */ `${shoelacePath}/shoelace-autoloader.js`);
90
+ }
91
+ catch (error) {
92
+ console.error("Failed to initialize Shoelace:", error);
93
+ throw error;
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @herdingbits/trailhead-shoelace
3
+ * Shoelace design system adapter for Trailhead
4
+ */
5
+ export { ShoelaceAdapter } from './adapter.js';
6
+ export { ShellApp } from './shell-app.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @herdingbits/trailhead-shoelace
3
+ * Shoelace design system adapter for Trailhead
4
+ */
5
+ export { ShoelaceAdapter } from './adapter.js';
6
+ export { ShellApp } from './shell-app.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shoelace Shell App
3
+ * Minimal wrapper for consistency with other adapters
4
+ */
5
+ import type { Trailhead } from '@herdingbits/trailhead-core';
6
+ export declare class ShellApp {
7
+ /**
8
+ * Mount the shell (no-op for Shoelace since adapter handles everything)
9
+ */
10
+ static mount(shell: Trailhead): void;
11
+ }
12
+ //# sourceMappingURL=shell-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-app.d.ts","sourceRoot":"","sources":["../src/shell-app.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,qBAAa,QAAQ;IACnB;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;CAKrC"}
@@ -0,0 +1,10 @@
1
+ export class ShellApp {
2
+ /**
3
+ * Mount the shell (no-op for Shoelace since adapter handles everything)
4
+ */
5
+ static mount(shell) {
6
+ // Shoelace adapter handles all UI via web components
7
+ // This is just a consistent API surface
8
+ console.log('[Trailhead] Shoelace shell mounted');
9
+ }
10
+ }
package/dist/shell.css ADDED
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Shell Styles
3
+ */
4
+
5
+ /* Reset */
6
+ * {
7
+ margin: 0;
8
+ padding: 0;
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ body {
13
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
14
+ -webkit-font-smoothing: antialiased;
15
+ -moz-osx-font-smoothing: grayscale;
16
+ display: flex;
17
+ height: 100vh;
18
+ overflow: hidden;
19
+ }
20
+
21
+ /* Sidebar */
22
+ #shell-sidebar {
23
+ width: 240px;
24
+ background-color: #1e293b;
25
+ color: white;
26
+ display: flex;
27
+ flex-direction: column;
28
+ transition: width 0.3s;
29
+ }
30
+
31
+ #shell-sidebar.collapsed {
32
+ width: 60px;
33
+ }
34
+
35
+ #shell-header {
36
+ padding: 1rem;
37
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: space-between;
41
+ }
42
+
43
+ #shell-title {
44
+ font-size: 1.25rem;
45
+ font-weight: 600;
46
+ }
47
+
48
+ #shell-sidebar.collapsed #shell-title {
49
+ display: none;
50
+ }
51
+
52
+ #shell-collapse {
53
+ background: none;
54
+ border: none;
55
+ color: white;
56
+ cursor: pointer;
57
+ padding: 0.5rem;
58
+ }
59
+
60
+ /* Navigation */
61
+ #shell-navigation {
62
+ flex: 1;
63
+ padding: 1rem 0;
64
+ overflow-y: auto;
65
+ }
66
+
67
+ .shell-nav-item {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 0.75rem;
71
+ padding: 0.75rem 1rem;
72
+ color: white;
73
+ text-decoration: none;
74
+ transition: background-color 0.2s;
75
+ border-left: 3px solid transparent;
76
+ }
77
+
78
+ .shell-nav-item:hover {
79
+ background-color: rgba(255, 255, 255, 0.1);
80
+ }
81
+
82
+ .shell-nav-item-active {
83
+ background-color: rgba(59, 130, 246, 0.2);
84
+ border-left-color: #3b82f6;
85
+ }
86
+
87
+ #shell-sidebar.collapsed .shell-nav-label {
88
+ display: none;
89
+ }
90
+
91
+ .shell-icon {
92
+ font-size: 1.25rem;
93
+ }
94
+
95
+ /* Main content */
96
+ #shell-main {
97
+ flex: 1;
98
+ background-color: #f8fafc;
99
+ overflow: auto;
100
+ }
101
+
102
+ #shell-content {
103
+ height: 100%;
104
+ }
105
+
106
+ /* Loading state */
107
+ .shell-loading {
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ height: 100%;
112
+ font-size: 1.25rem;
113
+ color: #64748b;
114
+ }
115
+
116
+ .shell-error {
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ height: 100%;
121
+ font-size: 1.25rem;
122
+ color: #ef4444;
123
+ }
124
+
125
+ /* Busy overlay */
126
+ #shell-busy-overlay {
127
+ position: fixed;
128
+ top: 0;
129
+ left: 0;
130
+ right: 0;
131
+ bottom: 0;
132
+ background-color: rgba(0, 0, 0, 0.5);
133
+ display: none;
134
+ align-items: center;
135
+ justify-content: center;
136
+ z-index: 9999;
137
+ }
138
+
139
+ .shell-busy-content {
140
+ background: white;
141
+ padding: 2rem;
142
+ border-radius: 8px;
143
+ text-align: center;
144
+ min-width: 200px;
145
+ }
146
+
147
+ .shell-spinner {
148
+ width: 40px;
149
+ height: 40px;
150
+ border: 4px solid #e5e7eb;
151
+ border-top-color: #3b82f6;
152
+ border-radius: 50%;
153
+ animation: shell-spin 0.8s linear infinite;
154
+ margin: 0 auto 1rem;
155
+ }
156
+
157
+ @keyframes shell-spin {
158
+ to { transform: rotate(360deg); }
159
+ }
160
+
161
+ .shell-busy-message {
162
+ color: #1e293b;
163
+ font-size: 1rem;
164
+ }
165
+
166
+ /* Toast notifications */
167
+ #shell-toast-container {
168
+ position: fixed;
169
+ top: 1rem;
170
+ right: 1rem;
171
+ z-index: 10000;
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 0.5rem;
175
+ }
176
+
177
+ .shell-toast {
178
+ padding: 1rem 1.5rem;
179
+ border-radius: 6px;
180
+ color: white;
181
+ font-size: 0.875rem;
182
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
183
+ opacity: 0;
184
+ transform: translateX(100%);
185
+ transition: all 0.3s;
186
+ max-width: 400px;
187
+ }
188
+
189
+ .shell-toast-show {
190
+ opacity: 1;
191
+ transform: translateX(0);
192
+ }
193
+
194
+ .shell-toast-success {
195
+ background-color: #10b981;
196
+ }
197
+
198
+ .shell-toast-error {
199
+ background-color: #ef4444;
200
+ }
201
+
202
+ .shell-toast-warning {
203
+ background-color: #f59e0b;
204
+ }
205
+
206
+ .shell-toast-info {
207
+ background-color: #3b82f6;
208
+ }
209
+
210
+ /* Dialog */
211
+ .shell-dialog-overlay {
212
+ position: fixed;
213
+ top: 0;
214
+ left: 0;
215
+ right: 0;
216
+ bottom: 0;
217
+ background-color: rgba(0, 0, 0, 0.5);
218
+ display: flex;
219
+ align-items: center;
220
+ justify-content: center;
221
+ z-index: 10001;
222
+ }
223
+
224
+ .shell-dialog {
225
+ background: white;
226
+ border-radius: 8px;
227
+ padding: 1.5rem;
228
+ min-width: 400px;
229
+ max-width: 600px;
230
+ box-shadow: 0 20px 25px rgba(0, 0, 0, 0.15);
231
+ }
232
+
233
+ .shell-dialog-title {
234
+ font-size: 1.25rem;
235
+ font-weight: 600;
236
+ color: #1e293b;
237
+ margin-bottom: 1rem;
238
+ }
239
+
240
+ .shell-dialog-message {
241
+ color: #64748b;
242
+ margin-bottom: 1.5rem;
243
+ line-height: 1.5;
244
+ }
245
+
246
+ .shell-dialog-buttons {
247
+ display: flex;
248
+ gap: 0.75rem;
249
+ justify-content: flex-end;
250
+ }
251
+
252
+ .shell-btn {
253
+ padding: 0.5rem 1rem;
254
+ border: none;
255
+ border-radius: 6px;
256
+ font-size: 0.875rem;
257
+ font-weight: 500;
258
+ cursor: pointer;
259
+ transition: all 0.2s;
260
+ }
261
+
262
+ .shell-btn-primary {
263
+ background-color: #3b82f6;
264
+ color: white;
265
+ }
266
+
267
+ .shell-btn-primary:hover {
268
+ background-color: #2563eb;
269
+ }
270
+
271
+ .shell-btn-secondary {
272
+ background-color: #e5e7eb;
273
+ color: #1e293b;
274
+ }
275
+
276
+ .shell-btn-secondary:hover {
277
+ background-color: #d1d5db;
278
+ }
279
+
280
+ .shell-btn-default {
281
+ background-color: #f3f4f6;
282
+ color: #1e293b;
283
+ }
284
+
285
+ .shell-btn-default:hover {
286
+ background-color: #e5e7eb;
287
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@herdingbits/trailhead-shoelace",
3
+ "version": "0.0.1",
4
+ "description": "Shoelace design system adapter for Trailhead micro-frontend framework",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./shell.css": "./dist/shell.css"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "clean": "rm -rf dist",
21
+ "build": "npm run clean && tsc && cp src/shell.css dist/"
22
+ },
23
+ "peerDependencies": {
24
+ "@herdingbits/trailhead-core": "^0.0.3",
25
+ "@shoelace-style/shoelace": "^2.20.0"
26
+ },
27
+ "devDependencies": {
28
+ "@herdingbits/trailhead-types": "^0.0.3",
29
+ "@shoelace-style/shoelace": "^2.20.1",
30
+ "typescript": "^5.9.3"
31
+ },
32
+ "keywords": [
33
+ "micro-frontend",
34
+ "shoelace",
35
+ "adapter",
36
+ "trailhead"
37
+ ],
38
+ "author": "HerdingBits",
39
+ "license": "MIT",
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/herdingbits/trailhead.git",
46
+ "directory": "packages/shoelace"
47
+ }
48
+ }