@sparkstudio/common-ui 1.0.18 → 1.0.20

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/dist/index.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ Alert: () => Alert,
23
24
  AppTile: () => AppTile,
24
25
  AppsView: () => AppsView,
25
26
  Body: () => Body,
@@ -43,20 +44,51 @@ __export(index_exports, {
43
44
  });
44
45
  module.exports = __toCommonJS(index_exports);
45
46
 
46
- // src/components/AppTile.tsx
47
+ // src/components/Alert.tsx
47
48
  var import_jsx_runtime = require("react/jsx-runtime");
49
+ var Alert = ({
50
+ variant = "info",
51
+ title,
52
+ dismissible = false,
53
+ className = "",
54
+ children,
55
+ onClose
56
+ }) => {
57
+ const classes = [
58
+ "alert",
59
+ `alert-${variant}`,
60
+ dismissible ? "alert-dismissible fade show" : "",
61
+ className
62
+ ].filter(Boolean).join(" ");
63
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "alert", className: classes, children: [
64
+ title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { className: "d-block mb-1", children: title }),
65
+ children,
66
+ dismissible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
67
+ "button",
68
+ {
69
+ type: "button",
70
+ className: "btn-close",
71
+ "aria-label": "Close",
72
+ onClick: onClose
73
+ }
74
+ )
75
+ ] });
76
+ };
77
+
78
+ // src/components/AppTile.tsx
79
+ var import_jsx_runtime2 = require("react/jsx-runtime");
48
80
  var AppTile = ({ app, onClick }) => {
49
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "col-auto", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
81
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "col-auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
50
82
  "button",
51
83
  {
52
84
  type: "button",
53
85
  className: "btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn",
54
86
  onClick: () => onClick?.(app),
55
87
  children: [
56
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "app-icon-tile d-flex align-items-center justify-content-center mb-1", children: app.icon }),
57
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "w-100 small text-truncate", children: [
88
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "app-icon-tile d-flex align-items-center justify-content-center mb-1", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "32px" }, children: app.icon }) }),
89
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "w-100 small text-truncate", children: [
58
90
  app.name,
59
- app.version && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { className: "text-muted ms-1", children: [
91
+ app.version && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("small", { className: "text-muted ms-1", children: [
60
92
  "v",
61
93
  app.version
62
94
  ] })
@@ -67,22 +99,22 @@ var AppTile = ({ app, onClick }) => {
67
99
  };
68
100
 
69
101
  // src/components/Body.tsx
70
- var import_jsx_runtime2 = require("react/jsx-runtime");
102
+ var import_jsx_runtime3 = require("react/jsx-runtime");
71
103
  function Body({ icon, title, description, children }) {
72
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("main", { className: "col p-4", children: [
73
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h2", { children: [
104
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "col p-4", children: [
105
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("h2", { children: [
74
106
  icon,
75
107
  " ",
76
108
  title
77
109
  ] }),
78
- description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: description }),
110
+ description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: description }),
79
111
  children
80
112
  ] });
81
113
  }
82
114
 
83
115
  // src/components/Button.tsx
84
116
  var import_react = require("react");
85
- var import_jsx_runtime3 = require("react/jsx-runtime");
117
+ var import_jsx_runtime4 = require("react/jsx-runtime");
86
118
  function Button({
87
119
  buttonClassName = "btn btn-primary btn-lg",
88
120
  type = "button",
@@ -116,15 +148,15 @@ function Button({
116
148
  onFinally?.();
117
149
  }
118
150
  };
119
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
151
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
120
152
  "button",
121
153
  {
122
154
  type,
123
155
  className: `${buttonClassName} ${loading ? "async-btn--loading" : ""}`,
124
156
  onClick: handleClick,
125
157
  disabled: disabled || loading,
126
- children: loading ? renderLoading?.() ?? loadingChildren ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
127
- showSpinner && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
158
+ children: loading ? renderLoading?.() ?? loadingChildren ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
159
+ showSpinner && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
128
160
  "span",
129
161
  {
130
162
  className: "spinner-border spinner-border-sm me-2 async-btn__spinner",
@@ -139,30 +171,30 @@ function Button({
139
171
  }
140
172
 
141
173
  // src/components/Footer.tsx
142
- var import_jsx_runtime4 = require("react/jsx-runtime");
174
+ var import_jsx_runtime5 = require("react/jsx-runtime");
143
175
  function Footer({ children }) {
144
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("footer", { className: "bg-dark text-white text-center py-2 mt-auto", children: children ?? "\xA9 2025 Your Site \u2014 All rights reserved" });
176
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("footer", { className: "bg-dark text-white text-center py-2 mt-auto", children: children ?? "\xA9 2025 Your Site \u2014 All rights reserved" });
145
177
  }
146
178
 
147
179
  // src/components/Header.tsx
148
- var import_jsx_runtime5 = require("react/jsx-runtime");
180
+ var import_jsx_runtime6 = require("react/jsx-runtime");
149
181
  function Header({ children }) {
150
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { className: "navbar navbar-dark bg-dark px-3 sticky-top", children: children ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "navbar-brand mb-0 h4", children: "My Website" }) });
182
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("nav", { className: "navbar navbar-dark bg-dark px-3 sticky-top", children: children ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "navbar-brand mb-0 h4", children: "My Website" }) });
151
183
  }
152
184
 
153
185
  // src/components/HeaderText.tsx
154
- var import_jsx_runtime6 = require("react/jsx-runtime");
186
+ var import_jsx_runtime7 = require("react/jsx-runtime");
155
187
  function HeaderText({ children }) {
156
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "navbar-brand mb-0 h4", children });
188
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "navbar-brand mb-0 h4", children });
157
189
  }
158
190
 
159
191
  // src/components/Icon.tsx
160
- var import_jsx_runtime7 = require("react/jsx-runtime");
192
+ var import_jsx_runtime8 = require("react/jsx-runtime");
161
193
  var ImageCard = ({
162
194
  src,
163
195
  alt
164
196
  }) => {
165
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
197
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
166
198
  "img",
167
199
  {
168
200
  src,
@@ -177,27 +209,27 @@ var ImageCard = ({
177
209
  };
178
210
 
179
211
  // src/components/NpmBadge.tsx
180
- var import_jsx_runtime8 = require("react/jsx-runtime");
212
+ var import_jsx_runtime9 = require("react/jsx-runtime");
181
213
  function NpmBadge({ packageName, packageLabel, packageUrl, color = "black", height = 22 }) {
182
214
  const encodedLabel = encodeURIComponent(packageLabel);
183
215
  const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;
184
216
  const npmUrl = packageUrl;
185
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href: npmUrl, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: badgeUrl, alt: `${packageName} version`, style: { height } }) });
217
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("a", { href: npmUrl, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: badgeUrl, alt: `${packageName} version`, style: { height } }) });
186
218
  }
187
219
 
188
220
  // src/components/navigation/Navigation.tsx
189
- var import_jsx_runtime9 = require("react/jsx-runtime");
221
+ var import_jsx_runtime10 = require("react/jsx-runtime");
190
222
  function Navigation({ title = "Navigation", children }) {
191
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("nav", { className: "col-auto p-3 h-100 d-flex flex-column", children: [
192
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h6", { className: "text-muted text-uppercase", children: title }),
193
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { className: "nav nav-pills flex-column gap-2 mt-3", children })
223
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("nav", { className: "col-auto p-3 h-100 d-flex flex-column", children: [
224
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h6", { className: "text-muted text-uppercase", children: title }),
225
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { className: "nav nav-pills flex-column gap-2 mt-3", children })
194
226
  ] });
195
227
  }
196
228
 
197
229
  // src/components/navigation/NavigationItem.tsx
198
- var import_jsx_runtime10 = require("react/jsx-runtime");
230
+ var import_jsx_runtime11 = require("react/jsx-runtime");
199
231
  function NavigationItem({ icon, title, type, active, onClick }) {
200
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("li", { className: "nav-item", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
232
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("li", { className: "nav-item", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
201
233
  "button",
202
234
  {
203
235
  type: "button",
@@ -214,7 +246,7 @@ function NavigationItem({ icon, title, type, active, onClick }) {
214
246
 
215
247
  // src/components/notifications/Notifications.tsx
216
248
  var import_react2 = require("react");
217
- var import_jsx_runtime11 = require("react/jsx-runtime");
249
+ var import_jsx_runtime12 = require("react/jsx-runtime");
218
250
  function Notifications({ notifications, onClose }) {
219
251
  (0, import_react2.useEffect)(() => {
220
252
  notifications.forEach((n) => {
@@ -223,19 +255,19 @@ function Notifications({ notifications, onClose }) {
223
255
  return () => clearTimeout(timer);
224
256
  });
225
257
  }, [notifications, onClose]);
226
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
258
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
227
259
  "div",
228
260
  {
229
261
  className: "position-fixed top-0 end-0",
230
262
  style: { zIndex: 1080, width: 340 },
231
- children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
263
+ children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
232
264
  "div",
233
265
  {
234
266
  className: `alert alert-${n.type ?? "info"} alert-dismissible fade show shadow-sm mb-2`,
235
267
  role: "alert",
236
268
  children: [
237
269
  n.message,
238
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
270
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
239
271
  "button",
240
272
  {
241
273
  type: "button",
@@ -254,7 +286,7 @@ function Notifications({ notifications, onClose }) {
254
286
 
255
287
  // src/components/notifications/NotificationsProvider.tsx
256
288
  var import_react3 = require("react");
257
- var import_jsx_runtime12 = require("react/jsx-runtime");
289
+ var import_jsx_runtime13 = require("react/jsx-runtime");
258
290
  var NotificationsContext = (0, import_react3.createContext)(
259
291
  void 0
260
292
  );
@@ -286,20 +318,20 @@ function NotificationsProvider({ children }) {
286
318
  timers.forEach((t) => t && clearTimeout(t));
287
319
  };
288
320
  }, [notifications, close]);
289
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(NotificationsContext.Provider, { value: { push }, children: [
290
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
321
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(NotificationsContext.Provider, { value: { push }, children: [
322
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
291
323
  "div",
292
324
  {
293
325
  className: "position-fixed top-0 end-0 p-3",
294
326
  style: { zIndex: 1080, width: 340 },
295
- children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
327
+ children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
296
328
  "div",
297
329
  {
298
330
  className: `alert alert-${n.type ?? "info"} alert-dismissible fade show shadow-sm mb-2`,
299
331
  role: "alert",
300
332
  children: [
301
333
  n.message,
302
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
334
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
303
335
  "button",
304
336
  {
305
337
  type: "button",
@@ -326,34 +358,34 @@ function UseNotifications() {
326
358
  }
327
359
 
328
360
  // src/components/views/AppsView.tsx
329
- var import_jsx_runtime13 = require("react/jsx-runtime");
361
+ var import_jsx_runtime14 = require("react/jsx-runtime");
330
362
  var AppsView = ({ apps, title, onAppClick }) => {
331
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
332
- title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h5", { className: "mb-3", children: title }),
333
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "row", children: apps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AppTile, { app, onClick: onAppClick }, app.id)) })
363
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
364
+ title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h5", { className: "mb-3", children: title }),
365
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "row", children: apps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AppTile, { app, onClick: onAppClick }, app.id)) })
334
366
  ] });
335
367
  };
336
368
 
337
369
  // src/components/wrappers/ContentContainer.tsx
338
- var import_jsx_runtime14 = require("react/jsx-runtime");
370
+ var import_jsx_runtime15 = require("react/jsx-runtime");
339
371
  function ContentContainer({ children }) {
340
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "container-fluid flex-grow-1", children });
372
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "container-fluid flex-grow-1", children });
341
373
  }
342
374
 
343
375
  // src/components/wrappers/ContentRow.tsx
344
- var import_jsx_runtime15 = require("react/jsx-runtime");
376
+ var import_jsx_runtime16 = require("react/jsx-runtime");
345
377
  function ContentRow({ children }) {
346
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "row h-100 flex-nowrap", children });
378
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "row h-100 flex-nowrap", children });
347
379
  }
348
380
 
349
381
  // src/components/wrappers/LayoutWrapper.tsx
350
- var import_jsx_runtime16 = require("react/jsx-runtime");
382
+ var import_jsx_runtime17 = require("react/jsx-runtime");
351
383
  function LayoutWrapper({ children }) {
352
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "d-flex flex-column min-vh-100", children });
384
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "d-flex flex-column min-vh-100", children });
353
385
  }
354
386
 
355
387
  // src/modal/Modal.tsx
356
- var import_jsx_runtime17 = require("react/jsx-runtime");
388
+ var import_jsx_runtime18 = require("react/jsx-runtime");
357
389
  var Modal = ({
358
390
  title,
359
391
  isOpen,
@@ -375,8 +407,8 @@ var Modal = ({
375
407
  const handleContentClick = (e) => {
376
408
  e.stopPropagation();
377
409
  };
378
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
379
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
410
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
411
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
380
412
  "div",
381
413
  {
382
414
  className: "modal-backdrop fade show",
@@ -384,7 +416,7 @@ var Modal = ({
384
416
  onClick: handleBackdropClick
385
417
  }
386
418
  ),
387
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
419
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
388
420
  "div",
389
421
  {
390
422
  className: "modal fade show d-block",
@@ -392,10 +424,10 @@ var Modal = ({
392
424
  role: "dialog",
393
425
  style: { zIndex: 1050 },
394
426
  onClick: handleBackdropClick,
395
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "modal-dialog modal-dialog-centered", role: "document", onClick: handleContentClick, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "modal-content shadow", children: [
396
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "modal-header", children: [
397
- title && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h5", { className: "modal-title", children: title }),
398
- showHeaderClose && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
427
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "modal-dialog modal-dialog-centered", role: "document", onClick: handleContentClick, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-content shadow", children: [
428
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-header", children: [
429
+ title && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h5", { className: "modal-title", children: title }),
430
+ showHeaderClose && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
399
431
  "button",
400
432
  {
401
433
  type: "button",
@@ -406,9 +438,9 @@ var Modal = ({
406
438
  }
407
439
  )
408
440
  ] }),
409
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "modal-body", children }),
410
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "modal-footer", children: [
411
- showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
441
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "modal-body", children }),
442
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-footer", children: [
443
+ showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
412
444
  "button",
413
445
  {
414
446
  type: "button",
@@ -418,7 +450,7 @@ var Modal = ({
418
450
  children: "Close"
419
451
  }
420
452
  ),
421
- onConfirm && showConfirmButton && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
453
+ onConfirm && showConfirmButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
422
454
  "button",
423
455
  {
424
456
  type: "button",
@@ -437,7 +469,7 @@ var Modal = ({
437
469
 
438
470
  // src/modal/ModalProvider.tsx
439
471
  var import_react4 = require("react");
440
- var import_jsx_runtime18 = require("react/jsx-runtime");
472
+ var import_jsx_runtime19 = require("react/jsx-runtime");
441
473
  var ModalContext = (0, import_react4.createContext)(void 0);
442
474
  function ModalProvider({ children }) {
443
475
  const [isOpen, setIsOpen] = (0, import_react4.useState)(false);
@@ -451,9 +483,9 @@ function ModalProvider({ children }) {
451
483
  const closeModal = (0, import_react4.useCallback)(() => {
452
484
  setIsOpen(false);
453
485
  }, []);
454
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(ModalContext.Provider, { value: { openModal, closeModal }, children: [
486
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(ModalContext.Provider, { value: { openModal, closeModal }, children: [
455
487
  children,
456
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
488
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
457
489
  Modal,
458
490
  {
459
491
  isOpen,
@@ -478,6 +510,7 @@ function UseModal() {
478
510
  }
479
511
  // Annotate the CommonJS export names for ESM import in node:
480
512
  0 && (module.exports = {
513
+ Alert,
481
514
  AppTile,
482
515
  AppsView,
483
516
  Body,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from \"./components/AppTile\";\nexport * from \"./components/Body\";\nexport * from \"./components/Button\";\nexport * from \"./components/Footer\";\nexport * from \"./components/Header\";\nexport * from \"./components/HeaderText\";\nexport * from \"./components/Icon\";\nexport * from \"./components/NpmBadge\";\nexport * from \"./components/navigation/Navigation\";\nexport * from \"./components/navigation/NavigationItem\";\nexport * from \"./components/notifications/Notifications\";\nexport * from \"./components/notifications/NotificationsProvider\";\nexport * from \"./components/views/AppsView\";\nexport * from \"./components/wrappers/ContentContainer\";\nexport * from \"./components/wrappers/ContentRow\";\nexport * from \"./components/wrappers/LayoutWrapper\";\nexport * from \"./modal/Modal\";\nexport * from \"./modal/ModalProvider\";\nexport * from \"./models/AppItem\";\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n {app.icon}\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary btn-lg\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n /** NEW: toggle visibility */\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div className=\"modal-dialog modal-dialog-centered\" role=\"document\" onClick={handleContentClick}>\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer */}\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","content","options"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/Alert.tsx","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from \"./components/Alert\";\nexport * from \"./components/AppTile\";\nexport * from \"./components/Body\";\nexport * from \"./components/Button\";\nexport * from \"./components/Footer\";\nexport * from \"./components/Header\";\nexport * from \"./components/HeaderText\";\nexport * from \"./components/Icon\";\nexport * from \"./components/NpmBadge\";\nexport * from \"./components/navigation/Navigation\";\nexport * from \"./components/navigation/NavigationItem\";\nexport * from \"./components/notifications/Notifications\";\nexport * from \"./components/notifications/NotificationsProvider\";\nexport * from \"./components/views/AppsView\";\nexport * from \"./components/wrappers/ContentContainer\";\nexport * from \"./components/wrappers/ContentRow\";\nexport * from \"./components/wrappers/LayoutWrapper\";\nexport * from \"./modal/Modal\";\nexport * from \"./modal/ModalProvider\";\nexport * from \"./models/AppItem\";\n","// components/Alert.tsx\r\nimport React from \"react\";\r\n\r\nexport type AlertVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\";\r\n\r\ninterface AlertProps {\r\n variant?: AlertVariant;\r\n title?: string;\r\n dismissible?: boolean;\r\n className?: string;\r\n children: React.ReactNode;\r\n onClose?: () => void;\r\n}\r\n\r\nexport const Alert: React.FC<AlertProps> = ({\r\n variant = \"info\",\r\n title,\r\n dismissible = false,\r\n className = \"\",\r\n children,\r\n onClose,\r\n}) => {\r\n const classes = [\r\n \"alert\",\r\n `alert-${variant}`,\r\n dismissible ? \"alert-dismissible fade show\" : \"\",\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \");\r\n\r\n return (\r\n <div role=\"alert\" className={classes}>\r\n {title && <strong className=\"d-block mb-1\">{title}</strong>}\r\n {children}\r\n\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n <span style={{fontSize:\"32px\"}}>{app.icon}</span>\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary btn-lg\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n /** NEW: toggle visibility */\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div className=\"modal-dialog modal-dialog-centered\" role=\"document\" onClick={handleContentClick}>\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer */}\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","content","options"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,17 @@
1
1
  import React$1, { JSX, ReactNode, MouseEvent } from 'react';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
 
4
+ type AlertVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
5
+ interface AlertProps {
6
+ variant?: AlertVariant;
7
+ title?: string;
8
+ dismissible?: boolean;
9
+ className?: string;
10
+ children: React$1.ReactNode;
11
+ onClose?: () => void;
12
+ }
13
+ declare const Alert: React$1.FC<AlertProps>;
14
+
4
15
  interface AppItem {
5
16
  id: string;
6
17
  name: string;
@@ -165,4 +176,4 @@ declare function ModalProvider({ children }: {
165
176
  }): react_jsx_runtime.JSX.Element;
166
177
  declare function UseModal(): ModalContextValue;
167
178
 
168
- export { type AppItem, type AppNotification, AppTile, AppsView, Body, Button, type ButtonProps, ContentContainer, ContentRow, Footer, Header, HeaderText, ImageCard, LayoutWrapper, Modal, type ModalOptions, type ModalProps, ModalProvider, Navigation, NavigationItem, type Notification, type NotificationType, Notifications, NotificationsProvider, NpmBadge, UseModal, UseNotifications };
179
+ export { Alert, type AlertVariant, type AppItem, type AppNotification, AppTile, AppsView, Body, Button, type ButtonProps, ContentContainer, ContentRow, Footer, Header, HeaderText, ImageCard, LayoutWrapper, Modal, type ModalOptions, type ModalProps, ModalProvider, Navigation, NavigationItem, type Notification, type NotificationType, Notifications, NotificationsProvider, NpmBadge, UseModal, UseNotifications };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import React$1, { JSX, ReactNode, MouseEvent } from 'react';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
 
4
+ type AlertVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
5
+ interface AlertProps {
6
+ variant?: AlertVariant;
7
+ title?: string;
8
+ dismissible?: boolean;
9
+ className?: string;
10
+ children: React$1.ReactNode;
11
+ onClose?: () => void;
12
+ }
13
+ declare const Alert: React$1.FC<AlertProps>;
14
+
4
15
  interface AppItem {
5
16
  id: string;
6
17
  name: string;
@@ -165,4 +176,4 @@ declare function ModalProvider({ children }: {
165
176
  }): react_jsx_runtime.JSX.Element;
166
177
  declare function UseModal(): ModalContextValue;
167
178
 
168
- export { type AppItem, type AppNotification, AppTile, AppsView, Body, Button, type ButtonProps, ContentContainer, ContentRow, Footer, Header, HeaderText, ImageCard, LayoutWrapper, Modal, type ModalOptions, type ModalProps, ModalProvider, Navigation, NavigationItem, type Notification, type NotificationType, Notifications, NotificationsProvider, NpmBadge, UseModal, UseNotifications };
179
+ export { Alert, type AlertVariant, type AppItem, type AppNotification, AppTile, AppsView, Body, Button, type ButtonProps, ContentContainer, ContentRow, Footer, Header, HeaderText, ImageCard, LayoutWrapper, Modal, type ModalOptions, type ModalProps, ModalProvider, Navigation, NavigationItem, type Notification, type NotificationType, Notifications, NotificationsProvider, NpmBadge, UseModal, UseNotifications };
package/dist/index.js CHANGED
@@ -1,17 +1,48 @@
1
- // src/components/AppTile.tsx
1
+ // src/components/Alert.tsx
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
+ var Alert = ({
4
+ variant = "info",
5
+ title,
6
+ dismissible = false,
7
+ className = "",
8
+ children,
9
+ onClose
10
+ }) => {
11
+ const classes = [
12
+ "alert",
13
+ `alert-${variant}`,
14
+ dismissible ? "alert-dismissible fade show" : "",
15
+ className
16
+ ].filter(Boolean).join(" ");
17
+ return /* @__PURE__ */ jsxs("div", { role: "alert", className: classes, children: [
18
+ title && /* @__PURE__ */ jsx("strong", { className: "d-block mb-1", children: title }),
19
+ children,
20
+ dismissible && /* @__PURE__ */ jsx(
21
+ "button",
22
+ {
23
+ type: "button",
24
+ className: "btn-close",
25
+ "aria-label": "Close",
26
+ onClick: onClose
27
+ }
28
+ )
29
+ ] });
30
+ };
31
+
32
+ // src/components/AppTile.tsx
33
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3
34
  var AppTile = ({ app, onClick }) => {
4
- return /* @__PURE__ */ jsx("div", { className: "col-auto", children: /* @__PURE__ */ jsxs(
35
+ return /* @__PURE__ */ jsx2("div", { className: "col-auto", children: /* @__PURE__ */ jsxs2(
5
36
  "button",
6
37
  {
7
38
  type: "button",
8
39
  className: "btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn",
9
40
  onClick: () => onClick?.(app),
10
41
  children: [
11
- /* @__PURE__ */ jsx("div", { className: "app-icon-tile d-flex align-items-center justify-content-center mb-1", children: app.icon }),
12
- /* @__PURE__ */ jsxs("span", { className: "w-100 small text-truncate", children: [
42
+ /* @__PURE__ */ jsx2("div", { className: "app-icon-tile d-flex align-items-center justify-content-center mb-1", children: /* @__PURE__ */ jsx2("span", { style: { fontSize: "32px" }, children: app.icon }) }),
43
+ /* @__PURE__ */ jsxs2("span", { className: "w-100 small text-truncate", children: [
13
44
  app.name,
14
- app.version && /* @__PURE__ */ jsxs("small", { className: "text-muted ms-1", children: [
45
+ app.version && /* @__PURE__ */ jsxs2("small", { className: "text-muted ms-1", children: [
15
46
  "v",
16
47
  app.version
17
48
  ] })
@@ -22,22 +53,22 @@ var AppTile = ({ app, onClick }) => {
22
53
  };
23
54
 
24
55
  // src/components/Body.tsx
25
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
56
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
26
57
  function Body({ icon, title, description, children }) {
27
- return /* @__PURE__ */ jsxs2("main", { className: "col p-4", children: [
28
- /* @__PURE__ */ jsxs2("h2", { children: [
58
+ return /* @__PURE__ */ jsxs3("main", { className: "col p-4", children: [
59
+ /* @__PURE__ */ jsxs3("h2", { children: [
29
60
  icon,
30
61
  " ",
31
62
  title
32
63
  ] }),
33
- description && /* @__PURE__ */ jsx2("p", { children: description }),
64
+ description && /* @__PURE__ */ jsx3("p", { children: description }),
34
65
  children
35
66
  ] });
36
67
  }
37
68
 
38
69
  // src/components/Button.tsx
39
70
  import { useState } from "react";
40
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
71
+ import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
41
72
  function Button({
42
73
  buttonClassName = "btn btn-primary btn-lg",
43
74
  type = "button",
@@ -71,15 +102,15 @@ function Button({
71
102
  onFinally?.();
72
103
  }
73
104
  };
74
- return /* @__PURE__ */ jsx3(
105
+ return /* @__PURE__ */ jsx4(
75
106
  "button",
76
107
  {
77
108
  type,
78
109
  className: `${buttonClassName} ${loading ? "async-btn--loading" : ""}`,
79
110
  onClick: handleClick,
80
111
  disabled: disabled || loading,
81
- children: loading ? renderLoading?.() ?? loadingChildren ?? /* @__PURE__ */ jsxs3(Fragment, { children: [
82
- showSpinner && /* @__PURE__ */ jsx3(
112
+ children: loading ? renderLoading?.() ?? loadingChildren ?? /* @__PURE__ */ jsxs4(Fragment, { children: [
113
+ showSpinner && /* @__PURE__ */ jsx4(
83
114
  "span",
84
115
  {
85
116
  className: "spinner-border spinner-border-sm me-2 async-btn__spinner",
@@ -94,30 +125,30 @@ function Button({
94
125
  }
95
126
 
96
127
  // src/components/Footer.tsx
97
- import { jsx as jsx4 } from "react/jsx-runtime";
128
+ import { jsx as jsx5 } from "react/jsx-runtime";
98
129
  function Footer({ children }) {
99
- return /* @__PURE__ */ jsx4("footer", { className: "bg-dark text-white text-center py-2 mt-auto", children: children ?? "\xA9 2025 Your Site \u2014 All rights reserved" });
130
+ return /* @__PURE__ */ jsx5("footer", { className: "bg-dark text-white text-center py-2 mt-auto", children: children ?? "\xA9 2025 Your Site \u2014 All rights reserved" });
100
131
  }
101
132
 
102
133
  // src/components/Header.tsx
103
- import { jsx as jsx5 } from "react/jsx-runtime";
134
+ import { jsx as jsx6 } from "react/jsx-runtime";
104
135
  function Header({ children }) {
105
- return /* @__PURE__ */ jsx5("nav", { className: "navbar navbar-dark bg-dark px-3 sticky-top", children: children ?? /* @__PURE__ */ jsx5("span", { className: "navbar-brand mb-0 h4", children: "My Website" }) });
136
+ return /* @__PURE__ */ jsx6("nav", { className: "navbar navbar-dark bg-dark px-3 sticky-top", children: children ?? /* @__PURE__ */ jsx6("span", { className: "navbar-brand mb-0 h4", children: "My Website" }) });
106
137
  }
107
138
 
108
139
  // src/components/HeaderText.tsx
109
- import { jsx as jsx6 } from "react/jsx-runtime";
140
+ import { jsx as jsx7 } from "react/jsx-runtime";
110
141
  function HeaderText({ children }) {
111
- return /* @__PURE__ */ jsx6("span", { className: "navbar-brand mb-0 h4", children });
142
+ return /* @__PURE__ */ jsx7("span", { className: "navbar-brand mb-0 h4", children });
112
143
  }
113
144
 
114
145
  // src/components/Icon.tsx
115
- import { jsx as jsx7 } from "react/jsx-runtime";
146
+ import { jsx as jsx8 } from "react/jsx-runtime";
116
147
  var ImageCard = ({
117
148
  src,
118
149
  alt
119
150
  }) => {
120
- return /* @__PURE__ */ jsx7(
151
+ return /* @__PURE__ */ jsx8(
121
152
  "img",
122
153
  {
123
154
  src,
@@ -132,27 +163,27 @@ var ImageCard = ({
132
163
  };
133
164
 
134
165
  // src/components/NpmBadge.tsx
135
- import { jsx as jsx8 } from "react/jsx-runtime";
166
+ import { jsx as jsx9 } from "react/jsx-runtime";
136
167
  function NpmBadge({ packageName, packageLabel, packageUrl, color = "black", height = 22 }) {
137
168
  const encodedLabel = encodeURIComponent(packageLabel);
138
169
  const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;
139
170
  const npmUrl = packageUrl;
140
- return /* @__PURE__ */ jsx8("a", { href: npmUrl, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx8("img", { src: badgeUrl, alt: `${packageName} version`, style: { height } }) });
171
+ return /* @__PURE__ */ jsx9("a", { href: npmUrl, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx9("img", { src: badgeUrl, alt: `${packageName} version`, style: { height } }) });
141
172
  }
142
173
 
143
174
  // src/components/navigation/Navigation.tsx
144
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
175
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
145
176
  function Navigation({ title = "Navigation", children }) {
146
- return /* @__PURE__ */ jsxs4("nav", { className: "col-auto p-3 h-100 d-flex flex-column", children: [
147
- /* @__PURE__ */ jsx9("h6", { className: "text-muted text-uppercase", children: title }),
148
- /* @__PURE__ */ jsx9("ul", { className: "nav nav-pills flex-column gap-2 mt-3", children })
177
+ return /* @__PURE__ */ jsxs5("nav", { className: "col-auto p-3 h-100 d-flex flex-column", children: [
178
+ /* @__PURE__ */ jsx10("h6", { className: "text-muted text-uppercase", children: title }),
179
+ /* @__PURE__ */ jsx10("ul", { className: "nav nav-pills flex-column gap-2 mt-3", children })
149
180
  ] });
150
181
  }
151
182
 
152
183
  // src/components/navigation/NavigationItem.tsx
153
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
184
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
154
185
  function NavigationItem({ icon, title, type, active, onClick }) {
155
- return /* @__PURE__ */ jsx10("li", { className: "nav-item", children: /* @__PURE__ */ jsxs5(
186
+ return /* @__PURE__ */ jsx11("li", { className: "nav-item", children: /* @__PURE__ */ jsxs6(
156
187
  "button",
157
188
  {
158
189
  type: "button",
@@ -169,7 +200,7 @@ function NavigationItem({ icon, title, type, active, onClick }) {
169
200
 
170
201
  // src/components/notifications/Notifications.tsx
171
202
  import { useEffect } from "react";
172
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
203
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
173
204
  function Notifications({ notifications, onClose }) {
174
205
  useEffect(() => {
175
206
  notifications.forEach((n) => {
@@ -178,19 +209,19 @@ function Notifications({ notifications, onClose }) {
178
209
  return () => clearTimeout(timer);
179
210
  });
180
211
  }, [notifications, onClose]);
181
- return /* @__PURE__ */ jsx11(
212
+ return /* @__PURE__ */ jsx12(
182
213
  "div",
183
214
  {
184
215
  className: "position-fixed top-0 end-0",
185
216
  style: { zIndex: 1080, width: 340 },
186
- children: notifications.map((n) => /* @__PURE__ */ jsxs6(
217
+ children: notifications.map((n) => /* @__PURE__ */ jsxs7(
187
218
  "div",
188
219
  {
189
220
  className: `alert alert-${n.type ?? "info"} alert-dismissible fade show shadow-sm mb-2`,
190
221
  role: "alert",
191
222
  children: [
192
223
  n.message,
193
- /* @__PURE__ */ jsx11(
224
+ /* @__PURE__ */ jsx12(
194
225
  "button",
195
226
  {
196
227
  type: "button",
@@ -215,7 +246,7 @@ import {
215
246
  useEffect as useEffect2,
216
247
  useState as useState2
217
248
  } from "react";
218
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
249
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
219
250
  var NotificationsContext = createContext(
220
251
  void 0
221
252
  );
@@ -247,20 +278,20 @@ function NotificationsProvider({ children }) {
247
278
  timers.forEach((t) => t && clearTimeout(t));
248
279
  };
249
280
  }, [notifications, close]);
250
- return /* @__PURE__ */ jsxs7(NotificationsContext.Provider, { value: { push }, children: [
251
- /* @__PURE__ */ jsx12(
281
+ return /* @__PURE__ */ jsxs8(NotificationsContext.Provider, { value: { push }, children: [
282
+ /* @__PURE__ */ jsx13(
252
283
  "div",
253
284
  {
254
285
  className: "position-fixed top-0 end-0 p-3",
255
286
  style: { zIndex: 1080, width: 340 },
256
- children: notifications.map((n) => /* @__PURE__ */ jsxs7(
287
+ children: notifications.map((n) => /* @__PURE__ */ jsxs8(
257
288
  "div",
258
289
  {
259
290
  className: `alert alert-${n.type ?? "info"} alert-dismissible fade show shadow-sm mb-2`,
260
291
  role: "alert",
261
292
  children: [
262
293
  n.message,
263
- /* @__PURE__ */ jsx12(
294
+ /* @__PURE__ */ jsx13(
264
295
  "button",
265
296
  {
266
297
  type: "button",
@@ -287,34 +318,34 @@ function UseNotifications() {
287
318
  }
288
319
 
289
320
  // src/components/views/AppsView.tsx
290
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
321
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
291
322
  var AppsView = ({ apps, title, onAppClick }) => {
292
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
293
- title && /* @__PURE__ */ jsx13("h5", { className: "mb-3", children: title }),
294
- /* @__PURE__ */ jsx13("div", { className: "row", children: apps.map((app) => /* @__PURE__ */ jsx13(AppTile, { app, onClick: onAppClick }, app.id)) })
323
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
324
+ title && /* @__PURE__ */ jsx14("h5", { className: "mb-3", children: title }),
325
+ /* @__PURE__ */ jsx14("div", { className: "row", children: apps.map((app) => /* @__PURE__ */ jsx14(AppTile, { app, onClick: onAppClick }, app.id)) })
295
326
  ] });
296
327
  };
297
328
 
298
329
  // src/components/wrappers/ContentContainer.tsx
299
- import { jsx as jsx14 } from "react/jsx-runtime";
330
+ import { jsx as jsx15 } from "react/jsx-runtime";
300
331
  function ContentContainer({ children }) {
301
- return /* @__PURE__ */ jsx14("div", { className: "container-fluid flex-grow-1", children });
332
+ return /* @__PURE__ */ jsx15("div", { className: "container-fluid flex-grow-1", children });
302
333
  }
303
334
 
304
335
  // src/components/wrappers/ContentRow.tsx
305
- import { jsx as jsx15 } from "react/jsx-runtime";
336
+ import { jsx as jsx16 } from "react/jsx-runtime";
306
337
  function ContentRow({ children }) {
307
- return /* @__PURE__ */ jsx15("div", { className: "row h-100 flex-nowrap", children });
338
+ return /* @__PURE__ */ jsx16("div", { className: "row h-100 flex-nowrap", children });
308
339
  }
309
340
 
310
341
  // src/components/wrappers/LayoutWrapper.tsx
311
- import { jsx as jsx16 } from "react/jsx-runtime";
342
+ import { jsx as jsx17 } from "react/jsx-runtime";
312
343
  function LayoutWrapper({ children }) {
313
- return /* @__PURE__ */ jsx16("div", { className: "d-flex flex-column min-vh-100", children });
344
+ return /* @__PURE__ */ jsx17("div", { className: "d-flex flex-column min-vh-100", children });
314
345
  }
315
346
 
316
347
  // src/modal/Modal.tsx
317
- import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
348
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
318
349
  var Modal = ({
319
350
  title,
320
351
  isOpen,
@@ -336,8 +367,8 @@ var Modal = ({
336
367
  const handleContentClick = (e) => {
337
368
  e.stopPropagation();
338
369
  };
339
- return /* @__PURE__ */ jsxs9(Fragment3, { children: [
340
- /* @__PURE__ */ jsx17(
370
+ return /* @__PURE__ */ jsxs10(Fragment3, { children: [
371
+ /* @__PURE__ */ jsx18(
341
372
  "div",
342
373
  {
343
374
  className: "modal-backdrop fade show",
@@ -345,7 +376,7 @@ var Modal = ({
345
376
  onClick: handleBackdropClick
346
377
  }
347
378
  ),
348
- /* @__PURE__ */ jsx17(
379
+ /* @__PURE__ */ jsx18(
349
380
  "div",
350
381
  {
351
382
  className: "modal fade show d-block",
@@ -353,10 +384,10 @@ var Modal = ({
353
384
  role: "dialog",
354
385
  style: { zIndex: 1050 },
355
386
  onClick: handleBackdropClick,
356
- children: /* @__PURE__ */ jsx17("div", { className: "modal-dialog modal-dialog-centered", role: "document", onClick: handleContentClick, children: /* @__PURE__ */ jsxs9("div", { className: "modal-content shadow", children: [
357
- /* @__PURE__ */ jsxs9("div", { className: "modal-header", children: [
358
- title && /* @__PURE__ */ jsx17("h5", { className: "modal-title", children: title }),
359
- showHeaderClose && /* @__PURE__ */ jsx17(
387
+ children: /* @__PURE__ */ jsx18("div", { className: "modal-dialog modal-dialog-centered", role: "document", onClick: handleContentClick, children: /* @__PURE__ */ jsxs10("div", { className: "modal-content shadow", children: [
388
+ /* @__PURE__ */ jsxs10("div", { className: "modal-header", children: [
389
+ title && /* @__PURE__ */ jsx18("h5", { className: "modal-title", children: title }),
390
+ showHeaderClose && /* @__PURE__ */ jsx18(
360
391
  "button",
361
392
  {
362
393
  type: "button",
@@ -367,9 +398,9 @@ var Modal = ({
367
398
  }
368
399
  )
369
400
  ] }),
370
- /* @__PURE__ */ jsx17("div", { className: "modal-body", children }),
371
- /* @__PURE__ */ jsxs9("div", { className: "modal-footer", children: [
372
- showCloseButton && /* @__PURE__ */ jsx17(
401
+ /* @__PURE__ */ jsx18("div", { className: "modal-body", children }),
402
+ /* @__PURE__ */ jsxs10("div", { className: "modal-footer", children: [
403
+ showCloseButton && /* @__PURE__ */ jsx18(
373
404
  "button",
374
405
  {
375
406
  type: "button",
@@ -379,7 +410,7 @@ var Modal = ({
379
410
  children: "Close"
380
411
  }
381
412
  ),
382
- onConfirm && showConfirmButton && /* @__PURE__ */ jsx17(
413
+ onConfirm && showConfirmButton && /* @__PURE__ */ jsx18(
383
414
  "button",
384
415
  {
385
416
  type: "button",
@@ -403,7 +434,7 @@ import {
403
434
  useContext as useContext2,
404
435
  useState as useState3
405
436
  } from "react";
406
- import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
437
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
407
438
  var ModalContext = createContext2(void 0);
408
439
  function ModalProvider({ children }) {
409
440
  const [isOpen, setIsOpen] = useState3(false);
@@ -417,9 +448,9 @@ function ModalProvider({ children }) {
417
448
  const closeModal = useCallback2(() => {
418
449
  setIsOpen(false);
419
450
  }, []);
420
- return /* @__PURE__ */ jsxs10(ModalContext.Provider, { value: { openModal, closeModal }, children: [
451
+ return /* @__PURE__ */ jsxs11(ModalContext.Provider, { value: { openModal, closeModal }, children: [
421
452
  children,
422
- /* @__PURE__ */ jsx18(
453
+ /* @__PURE__ */ jsx19(
423
454
  Modal,
424
455
  {
425
456
  isOpen,
@@ -443,6 +474,7 @@ function UseModal() {
443
474
  return ctx;
444
475
  }
445
476
  export {
477
+ Alert,
446
478
  AppTile,
447
479
  AppsView,
448
480
  Body,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n {app.icon}\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary btn-lg\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n /** NEW: toggle visibility */\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div className=\"modal-dialog modal-dialog-centered\" role=\"document\" onClick={handleContentClick}>\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer */}\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","jsx","jsx","jsx","jsx","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","useEffect","useState","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","jsx","Fragment","jsx","jsxs","createContext","useCallback","useContext","useState","jsx","jsxs","createContext","useState","useCallback","content","options","useContext"]}
1
+ {"version":3,"sources":["../src/components/Alert.tsx","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["// components/Alert.tsx\r\nimport React from \"react\";\r\n\r\nexport type AlertVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\";\r\n\r\ninterface AlertProps {\r\n variant?: AlertVariant;\r\n title?: string;\r\n dismissible?: boolean;\r\n className?: string;\r\n children: React.ReactNode;\r\n onClose?: () => void;\r\n}\r\n\r\nexport const Alert: React.FC<AlertProps> = ({\r\n variant = \"info\",\r\n title,\r\n dismissible = false,\r\n className = \"\",\r\n children,\r\n onClose,\r\n}) => {\r\n const classes = [\r\n \"alert\",\r\n `alert-${variant}`,\r\n dismissible ? \"alert-dismissible fade show\" : \"\",\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \");\r\n\r\n return (\r\n <div role=\"alert\" className={classes}>\r\n {title && <strong className=\"d-block mb-1\">{title}</strong>}\r\n {children}\r\n\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n <span style={{fontSize:\"32px\"}}>{app.icon}</span>\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary btn-lg\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n /** NEW: toggle visibility */\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div className=\"modal-dialog modal-dialog-centered\" role=\"document\" onClick={handleContentClick}>\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer */}\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsx","jsx","jsx","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","useEffect","useState","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","jsx","Fragment","jsx","jsxs","createContext","useCallback","useContext","useState","jsx","jsxs","createContext","useState","useCallback","content","options","useContext"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sparkstudio/common-ui",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",