@sensorario/sg-components 0.0.99 → 0.0.101

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.
@@ -0,0 +1,14 @@
1
+ import './AppLauncher.css';
2
+ export declare const DEFAULT_APPS_URL = "https://api.simonegentili.com/heimdall/launcher";
3
+ export type LauncherApp = {
4
+ name: string;
5
+ url: string;
6
+ };
7
+ interface AppLauncherProps {
8
+ /** Endpoint returning `{ apps: LauncherApp[] }` - the enabled apps, managed from Heimdall. */
9
+ appsUrl?: string;
10
+ /** Accessible name of the grid button - this library has no i18n of its own. */
11
+ label?: string;
12
+ }
13
+ export declare const AppLauncher: ({ appsUrl, label }: AppLauncherProps) => import("react/jsx-runtime").JSX.Element;
14
+ export default AppLauncher;
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import AppLauncher from './AppLauncher';
3
+ declare const meta: Meta<typeof AppLauncher>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AppLauncher>;
6
+ export declare const Default: Story;
7
+ export declare const Live: Story;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import './Icon.css';
3
- export type IconName = 'menu' | 'layout' | 'edit' | 'help-circle' | 'check' | 'x' | 'file-plus' | 'link' | 'share-2' | 'download' | 'book' | 'printer' | 'eye' | 'columns' | 'sidebar-left' | 'sidebar-right' | 'play' | 'pause' | 'volume-2' | 'tech-node' | 'tech-go' | 'tech-php';
3
+ export type IconName = 'menu' | 'layout' | 'edit' | 'help-circle' | 'check' | 'x' | 'file-plus' | 'link' | 'share-2' | 'download' | 'book' | 'printer' | 'eye' | 'columns' | 'sidebar-left' | 'sidebar-right' | 'play' | 'pause' | 'volume-2' | 'tech-node' | 'tech-go' | 'tech-php' | 'grid';
4
4
  export interface IconProps extends React.SVGAttributes<SVGSVGElement> {
5
5
  name: IconName;
6
6
  size?: number;
@@ -15,6 +15,8 @@ interface QuadratoHeaderProps {
15
15
  onLogout?: () => void;
16
16
  /** Notified on mount and after every login/logout with the current auth state. */
17
17
  onUserAuthenticated?: (isAuthenticated: boolean, username: string | null) => void;
18
+ /** Endpoint of the app launcher menu. Default: the Heimdall-managed list on api.simonegentili.com. */
19
+ appsUrl?: string;
18
20
  }
19
21
  export interface QuadratoHeaderHandle {
20
22
  /** Forces the login modal open, e.g. when a consumer action requires auth first. */
package/dist/index.d.ts CHANGED
@@ -15,3 +15,4 @@ export * from './components/PasswordInput/PasswordInput';
15
15
  export * from './components/ColorPicker/ColorPicker';
16
16
  export * from './components/FontPicker/FontPicker';
17
17
  export * from './components/Toggle/Toggle';
18
+ export * from './components/AppLauncher/AppLauncher';
package/dist/index.es.js CHANGED
@@ -211,7 +211,24 @@ var u = {
211
211
  ] }),
212
212
  "tech-node": /* @__PURE__ */ c("polygon", { points: "12,3 19.8,7.5 19.8,16.5 12,21 4.2,16.5 4.2,7.5" }),
213
213
  "tech-go": /* @__PURE__ */ c("polygon", { points: "12,3 21,12 12,21 3,12" }),
214
- "tech-php": /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("path", { d: "M9 4c-1.5 0-2.5 1-2.5 2.5v3c0 1-.5 1.5-1.5 2.5 1 1 1.5 1.5 1.5 2.5v3c0 1.5 1 2.5 2.5 2.5" }), /* @__PURE__ */ c("path", { d: "M15 4c1.5 0 2.5 1 2.5 2.5v3c0 1 .5 1.5 1.5 2.5-1 1-1.5 1.5-1.5 2.5v3c0 1.5-1 2.5-2.5 2.5" })] })
214
+ "tech-php": /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("path", { d: "M9 4c-1.5 0-2.5 1-2.5 2.5v3c0 1-.5 1.5-1.5 2.5 1 1 1.5 1.5 1.5 2.5v3c0 1.5 1 2.5 2.5 2.5" }), /* @__PURE__ */ c("path", { d: "M15 4c1.5 0 2.5 1 2.5 2.5v3c0 1 .5 1.5 1.5 2.5-1 1-1.5 1.5-1.5 2.5v3c0 1.5-1 2.5-2.5 2.5" })] }),
215
+ grid: /* @__PURE__ */ c("g", {
216
+ fill: "currentColor",
217
+ stroke: "none",
218
+ children: [
219
+ 5,
220
+ 12,
221
+ 19
222
+ ].flatMap((e) => [
223
+ 5,
224
+ 12,
225
+ 19
226
+ ].map((t) => /* @__PURE__ */ c("circle", {
227
+ cx: t,
228
+ cy: e,
229
+ r: "2"
230
+ }, `${t}-${e}`)))
231
+ })
215
232
  }, d = ({ name: e, size: t = 18, ...n }) => /* @__PURE__ */ c("svg", {
216
233
  className: "sg-icon",
217
234
  width: t,
@@ -330,28 +347,81 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
330
347
  onNavigate: e,
331
348
  title: "Simone Gentili - senior web developer, tech author and chess enthusiast",
332
349
  homePageKey: "home"
333
- }), C = ({ isLoggedIn: e, handleLogin: t, handleLogout: n }) => /* @__PURE__ */ c(s, { children: e ? /* @__PURE__ */ c("button", {
350
+ }), C = "https://api.simonegentili.com/heimdall/launcher", w = ({ appsUrl: e = C, label: t = "App" }) => {
351
+ let [r, i] = o(!1), [s, u] = o(null), [f, p] = o(!1), m = a(null);
352
+ return n(() => {
353
+ !r || s !== null || fetch(e).then((e) => e.ok ? e.json() : Promise.reject(e.status)).then((e) => u(e.apps)).catch(() => p(!0));
354
+ }, [
355
+ r,
356
+ s,
357
+ e
358
+ ]), n(() => {
359
+ if (!r) return;
360
+ let e = (e) => {
361
+ m.current?.contains(e.target) || i(!1);
362
+ }, t = (e) => {
363
+ e.key === "Escape" && i(!1);
364
+ };
365
+ return document.addEventListener("pointerdown", e), document.addEventListener("keydown", t), () => {
366
+ document.removeEventListener("pointerdown", e), document.removeEventListener("keydown", t);
367
+ };
368
+ }, [r]), /* @__PURE__ */ l("div", {
369
+ className: "sg-app-launcher",
370
+ ref: m,
371
+ children: [/* @__PURE__ */ c("button", {
372
+ type: "button",
373
+ className: "sg-app-launcher-toggle",
374
+ "aria-label": t,
375
+ title: t,
376
+ "aria-expanded": r,
377
+ onClick: () => {
378
+ r || p(!1), i(!r);
379
+ },
380
+ children: /* @__PURE__ */ c(d, {
381
+ name: "grid",
382
+ size: 22
383
+ })
384
+ }), r && /* @__PURE__ */ c("div", {
385
+ className: "sg-app-launcher-panel",
386
+ children: f ? /* @__PURE__ */ c("p", {
387
+ className: "sg-app-launcher-message",
388
+ children: "Impossibile caricare le app."
389
+ }) : s === null ? /* @__PURE__ */ c("p", {
390
+ className: "sg-app-launcher-message",
391
+ children: "Caricamento…"
392
+ }) : /* @__PURE__ */ c("ul", {
393
+ className: "sg-app-launcher-grid",
394
+ children: s.map((e) => /* @__PURE__ */ c("li", { children: /* @__PURE__ */ l("a", {
395
+ href: e.url,
396
+ className: new URL(e.url).origin === window.location.origin ? "sg-app-launcher-app current" : "sg-app-launcher-app",
397
+ children: [/* @__PURE__ */ c("span", {
398
+ className: "sg-app-launcher-tile",
399
+ "aria-hidden": "true",
400
+ children: e.name.charAt(0).toUpperCase()
401
+ }), /* @__PURE__ */ c("span", {
402
+ className: "sg-app-launcher-name",
403
+ children: e.name
404
+ })]
405
+ }) }, e.url))
406
+ })
407
+ })]
408
+ });
409
+ }, T = ({ isLoggedIn: e, handleLogin: t, handleLogout: n }) => /* @__PURE__ */ c(s, { children: e ? /* @__PURE__ */ c("button", {
334
410
  onClick: n,
335
- style: {
336
- fontSize: "0.9rem",
337
- padding: "0.4rem 1rem"
338
- },
411
+ className: "sg-authenticator-button",
339
412
  children: "logout"
340
413
  }) : /* @__PURE__ */ c("button", {
341
414
  onClick: t,
342
- style: {
343
- fontSize: "0.9rem",
344
- padding: "0.4rem 1rem"
345
- },
415
+ className: "sg-authenticator-button",
346
416
  children: "Login"
347
- }) }), w = 220, T = ({ open: t, onClose: r, title: i, icon: a, children: s, buttons: u, footer: d, closeLabel: p = "Close", className: m }) => {
417
+ }) }), E = 220, D = ({ open: t, onClose: r, title: i, icon: a, children: s, buttons: u, footer: d, closeLabel: p = "Close", className: m }) => {
348
418
  let [h, g] = o(!1), [_, v] = o({
349
419
  x: 0,
350
420
  y: 0
351
421
  }), y = e.useRef(null), [b, x] = o(!1), S = (e) => {
352
422
  h || (g(!0), setTimeout(() => {
353
423
  g(!1), e();
354
- }, w));
424
+ }, E));
355
425
  };
356
426
  n(() => {
357
427
  if (!t) return;
@@ -360,12 +430,12 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
360
430
  };
361
431
  return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
362
432
  }, [t, r]);
363
- let [C, T] = o(t);
364
- if (t !== C && (T(t), t && v({
433
+ let [C, w] = o(t);
434
+ if (t !== C && (w(t), t && v({
365
435
  x: 0,
366
436
  y: 0
367
437
  })), !t) return null;
368
- function E(e) {
438
+ function T(e) {
369
439
  e.target.closest(".modal-close") || (y.current = {
370
440
  pointerX: e.clientX,
371
441
  pointerY: e.clientY,
@@ -397,7 +467,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
397
467
  children: [
398
468
  /* @__PURE__ */ l("div", {
399
469
  className: `modal-header${b ? " modal-header-dragging" : ""}`,
400
- onPointerDown: E,
470
+ onPointerDown: T,
401
471
  onPointerMove: D,
402
472
  onPointerUp: O,
403
473
  onPointerCancel: O,
@@ -439,7 +509,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
439
509
  ]
440
510
  })
441
511
  });
442
- }, E = ({ label: e, invalid: t, className: n, id: i, ...a }) => {
512
+ }, O = ({ label: e, invalid: t, className: n, id: i, ...a }) => {
443
513
  let o = r(), s = i ?? o;
444
514
  return /* @__PURE__ */ l("div", {
445
515
  className: "input-wrapper",
@@ -457,7 +527,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
457
527
  ...a
458
528
  })]
459
529
  });
460
- }, D = ({ label: e, className: t, id: n, ...i }) => {
530
+ }, k = ({ label: e, className: t, id: n, ...i }) => {
461
531
  let a = r(), o = n ?? a;
462
532
  return /* @__PURE__ */ l("div", {
463
533
  className: "input-wrapper",
@@ -472,9 +542,9 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
472
542
  ...i
473
543
  })]
474
544
  });
475
- }, O = ({ open: e, onClose: t, onLogin: n }) => {
545
+ }, A = ({ open: e, onClose: t, onLogin: n }) => {
476
546
  let [r, i] = o(""), [a, s] = o("");
477
- return /* @__PURE__ */ c(T, {
547
+ return /* @__PURE__ */ c(D, {
478
548
  open: e,
479
549
  onClose: t,
480
550
  title: "Login",
@@ -483,13 +553,13 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
483
553
  e.preventDefault(), n(r, a);
484
554
  },
485
555
  children: [
486
- /* @__PURE__ */ c(E, {
556
+ /* @__PURE__ */ c(O, {
487
557
  label: "Username",
488
558
  value: r,
489
559
  onChange: (e) => i(e.target.value),
490
560
  autoFocus: !0
491
561
  }),
492
- /* @__PURE__ */ c(D, {
562
+ /* @__PURE__ */ c(k, {
493
563
  label: "Password",
494
564
  value: a,
495
565
  onChange: (e) => s(e.target.value)
@@ -502,57 +572,57 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
502
572
  ]
503
573
  })
504
574
  });
505
- }, k = "simonegentili.com-access-token", A = (e) => document.cookie.split("; ").some((t) => t.startsWith(`${e}=`) && t.slice(e.length + 1).length > 0), j = (e) => {
575
+ }, j = "simonegentili.com-access-token", M = (e) => document.cookie.split("; ").some((t) => t.startsWith(`${e}=`) && t.slice(e.length + 1).length > 0), N = (e) => {
506
576
  let t = document.cookie.split("; ").find((t) => t.startsWith(`${e}=`));
507
577
  return t ? t.slice(e.length + 1) : null;
508
- }, M = (e, t) => {
578
+ }, P = (e, t) => {
509
579
  try {
510
580
  return JSON.parse(atob(e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/")))[t] ?? null;
511
581
  } catch {
512
582
  return null;
513
583
  }
514
- }, N = t(({ title: e = "Quadrato", homePageKey: t = "home", onNavigate: r, cookieName: a = k, username: u = null, usernameJwtField: d = "sub", onLogin: f, onLogout: p, onUserAuthenticated: m }, h) => {
515
- let [g, _] = o(() => A(a)), [v, y] = o(!1);
516
- i(h, () => ({ openLoginModal: () => y(!0) }));
517
- let b = u ?? (g ? M(j(a) ?? "", d) : null);
584
+ }, F = t(({ title: e = "Quadrato", homePageKey: t = "home", onNavigate: r, cookieName: a = j, username: u = null, usernameJwtField: d = "sub", onLogin: f, onLogout: p, onUserAuthenticated: m, appsUrl: h }, g) => {
585
+ let [_, v] = o(() => M(a)), [y, b] = o(!1);
586
+ i(g, () => ({ openLoginModal: () => b(!0) }));
587
+ let S = u ?? (_ ? P(N(a) ?? "", d) : null);
518
588
  return n(() => {
519
- m?.(g, g ? b : null);
520
- }, []), /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c(x, {
589
+ m?.(_, _ ? S : null);
590
+ }, []), /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ l(x, {
521
591
  onNavigate: r,
522
592
  title: e,
523
593
  homePageKey: t,
524
594
  className: "quadrato-header",
525
- children: /* @__PURE__ */ l("div", {
595
+ children: [/* @__PURE__ */ c(w, { appsUrl: h }), /* @__PURE__ */ l("div", {
526
596
  className: "quadrato-header-auth",
527
- children: [g && b && /* @__PURE__ */ c("span", {
597
+ children: [_ && S && /* @__PURE__ */ c("span", {
528
598
  className: "quadrato-header-username",
529
- children: b
530
- }), /* @__PURE__ */ c(C, {
531
- isLoggedIn: g,
532
- handleLogin: () => y(!0),
599
+ children: S
600
+ }), /* @__PURE__ */ c(T, {
601
+ isLoggedIn: _,
602
+ handleLogin: () => b(!0),
533
603
  handleLogout: () => {
534
604
  p?.();
535
- let e = A(a);
536
- _(e), m?.(e, null);
605
+ let e = M(a);
606
+ v(e), m?.(e, null);
537
607
  }
538
608
  })]
539
- })
540
- }), /* @__PURE__ */ c(O, {
541
- open: v,
542
- onClose: () => y(!1),
609
+ })]
610
+ }), /* @__PURE__ */ c(A, {
611
+ open: y,
612
+ onClose: () => b(!1),
543
613
  onLogin: async (e, t) => {
544
614
  await f(e, t);
545
- let n = A(a);
546
- _(n), y(!1), m?.(n, n ? u ?? e : null);
615
+ let n = M(a);
616
+ v(n), b(!1), m?.(n, n ? u ?? e : null);
547
617
  }
548
618
  })] });
549
619
  });
550
- N.displayName = "QuadratoHeader";
620
+ F.displayName = "QuadratoHeader";
551
621
  //#endregion
552
622
  //#region src/components/SetPasswordModal/SetPasswordModal.tsx
553
- var P = ({ open: e, onClose: t, onSubmit: n }) => {
623
+ var I = ({ open: e, onClose: t, onSubmit: n }) => {
554
624
  let [r, i] = o(""), [a, s] = o(""), [u, d] = o("");
555
- return /* @__PURE__ */ c(T, {
625
+ return /* @__PURE__ */ c(D, {
556
626
  open: e,
557
627
  onClose: t,
558
628
  title: "Imposta una nuova password",
@@ -570,13 +640,13 @@ var P = ({ open: e, onClose: t, onSubmit: n }) => {
570
640
  d(""), n(r);
571
641
  },
572
642
  children: [
573
- /* @__PURE__ */ c(D, {
643
+ /* @__PURE__ */ c(k, {
574
644
  label: "Nuova password",
575
645
  value: r,
576
646
  onChange: (e) => i(e.target.value),
577
647
  autoFocus: !0
578
648
  }),
579
- /* @__PURE__ */ c(D, {
649
+ /* @__PURE__ */ c(k, {
580
650
  label: "Conferma password",
581
651
  value: a,
582
652
  onChange: (e) => s(e.target.value)
@@ -593,7 +663,7 @@ var P = ({ open: e, onClose: t, onSubmit: n }) => {
593
663
  ]
594
664
  })
595
665
  });
596
- }, F = ({ value: e, onChange: t, swatches: r }) => {
666
+ }, L = ({ value: e, onChange: t, swatches: r }) => {
597
667
  let [i, s] = o(!1), u = a(null);
598
668
  return n(() => {
599
669
  if (!i) return;
@@ -642,7 +712,7 @@ var P = ({ open: e, onClose: t, onSubmit: n }) => {
642
712
  })]
643
713
  })]
644
714
  });
645
- }, I = (e) => e.split(",")[0].replace(/'/g, ""), L = ({ value: e, onChange: t, options: r }) => {
715
+ }, R = (e) => e.split(",")[0].replace(/'/g, ""), z = ({ value: e, onChange: t, options: r }) => {
646
716
  let [i, s] = o(!1), u = a(null);
647
717
  return n(() => {
648
718
  if (!i) return;
@@ -664,7 +734,7 @@ var P = ({ open: e, onClose: t, onSubmit: n }) => {
664
734
  style: { fontFamily: e },
665
735
  children: [/* @__PURE__ */ c("span", {
666
736
  className: "sg-font-picker-toggle-label",
667
- children: I(e)
737
+ children: R(e)
668
738
  }), /* @__PURE__ */ c("span", {
669
739
  className: "sg-font-picker-toggle-caret",
670
740
  children: i ? "▲" : "▼"
@@ -678,11 +748,11 @@ var P = ({ open: e, onClose: t, onSubmit: n }) => {
678
748
  t(n), s(!1);
679
749
  },
680
750
  style: { fontFamily: n },
681
- children: I(n)
751
+ children: R(n)
682
752
  }) }, n))
683
753
  })]
684
754
  });
685
- }, R = ({ checked: e, onChange: t, label: n }) => /* @__PURE__ */ l("label", {
755
+ }, B = ({ checked: e, onChange: t, label: n }) => /* @__PURE__ */ l("label", {
686
756
  className: "sg-toggle",
687
757
  children: [
688
758
  /* @__PURE__ */ c("input", {
@@ -702,4 +772,4 @@ var P = ({ open: e, onClose: t, onSubmit: n }) => {
702
772
  ]
703
773
  });
704
774
  //#endregion
705
- export { C as Authenticator, f as Button, F as ColorPicker, v as CookieConsent, L as FontPicker, p as Footer, x as Header, d as Icon, E as Input, T as Modal, D as PasswordInput, N as QuadratoHeader, b as SGFooter, S as SGHeader, P as SetPasswordModal, R as Toggle };
775
+ export { w as AppLauncher, T as Authenticator, f as Button, L as ColorPicker, v as CookieConsent, C as DEFAULT_APPS_URL, z as FontPicker, p as Footer, x as Header, d as Icon, O as Input, D as Modal, k as PasswordInput, F as QuadratoHeader, b as SGFooter, S as SGHeader, I as SetPasswordModal, B as Toggle };
@@ -1,2 +1,2 @@
1
- .custom-button{border-radius:var(--button-radius);background:var(--button-bg);color:var(--button-color);cursor:pointer;font-size:var(--primary-font);font-weight:600;font-family:var(--font-family);box-shadow:var(--button-shadow);transition:background .15s var(--button-ease-standard), transform var(--button-ease-bounce) .2s;border:none;padding:8px 20px}.custom-button:hover:not(:disabled){background:var(--button-bg-hover);transform:translateY(-1px)}.custom-button:active:not(:disabled){transform:scale(.97)}.custom-button:disabled{opacity:.6;cursor:default}.custom-button-with-icon{align-items:center;gap:8px;display:inline-flex}.custom-button-label-visually-hidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.sg-icon{vertical-align:middle;flex-shrink:0;display:inline-block}.footer{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;justify-content:space-between;align-items:center;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.footer a{color:#1ea7fd;text-decoration:none}.footer a:hover{text-decoration:underline}.cookie-consent{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;z-index:1000;box-sizing:border-box;flex-wrap:wrap;justify-content:center;align-items:center;gap:16px;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.cookie-consent-text{flex:320px;margin:0}.cookie-consent a{color:#1ea7fd;text-decoration:none}.cookie-consent a:hover{text-decoration:underline}.cookie-consent-accept{flex:none}.logo-text{font-size:var(--font-size-h1);font-family:var(--font-family);margin:0;font-weight:400}.header{z-index:100;width:100%;font-size:var(--font-size);background-color:#fff;border-bottom:1px solid #e1e5e9;position:sticky;top:0;box-shadow:0 2px 4px #0000001a}.header-container{justify-content:flex-start;align-items:center;max-width:1200px;margin:0 auto;padding:16px;display:flex}.header-actions{align-items:center;gap:12px;margin-left:auto;display:flex}.logo{cursor:pointer;color:#333;font-size:24px;font-weight:700;transition:color .2s}.logo:hover{color:#007acc}.logo-full{display:inline}.logo-short{display:none}@media (width<=768px){.header-container{padding:12px 16px}.logo{font-size:var(--font-size)}.logo-full{display:none}.logo-short{display:inline}}@media (width<=480px){.header-container{padding:8px 12px}.logo{font-size:var(--font-size)}}.modal-overlay{background:var(--modal-overlay);z-index:1000;justify-content:center;align-items:center;width:100vw;height:100vh;animation:.25s ease-out sg-modal-overlay-fade-in;display:flex;position:fixed;top:0;left:0}.modal-overlay.modal-overlay-closing{animation:.22s ease-in forwards sg-modal-overlay-fade-out}.modal-content{--drag-x:0px;--drag-y:0px;background:var(--modal-bg);border-radius:var(--primary-radius);font-size:var(--primary-font);min-width:320px;max-width:calc(100vw - 40px);max-height:90vh;transform:translate(var(--drag-x), var(--drag-y));flex-direction:column;animation:.3s ease-out sg-modal-slide-in;display:flex;overflow:hidden;box-shadow:0 2px 16px #00000026}.modal-content.modal-content-closing{animation:.22s ease-in forwards sg-modal-slide-out}@keyframes sg-modal-overlay-fade-in{0%{opacity:0}to{opacity:1}}@keyframes sg-modal-overlay-fade-out{0%{opacity:1}to{opacity:0}}@keyframes sg-modal-slide-in{0%{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}to{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}}@keyframes sg-modal-slide-out{0%{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}to{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}}.modal-header{background:var(--primary-bg);border-top-left-radius:var(--primary-radius);border-top-right-radius:var(--primary-radius);cursor:grab;touch-action:none;flex:none;align-items:center;gap:8px;padding:16px;display:flex}.modal-header-dragging{cursor:grabbing;-webkit-user-select:none;user-select:none}.modal-icon{color:var(--modal-title-color);display:inline-flex}.modal-title{color:var(--modal-title-color);font-family:var(--font-family);font-size:var(--primary-font);flex:1;margin:0}.modal-close{cursor:pointer;color:var(--modal-title-color);background:0 0;border:none;padding:4px 8px;font-size:20px;line-height:1}.modal-close:disabled{cursor:default;opacity:.6}.modal-children{font-family:var(--font-family);padding:16px;overflow-y:auto}.modal-footer{border-top:1px solid var(--primary-border);flex-wrap:wrap;flex:none;justify-content:flex-end;gap:8px;padding:12px 16px;display:flex}.input-label{font-weight:500;font-family:var(--font-family);font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field--invalid{background-color:#ffe5e5;border-color:#c00}.input-wrapper{margin-bottom:16px}.input-label{font-weight:500;font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field{box-sizing:border-box;border-radius:var(--radius);width:100%;font-size:var(--primary-font);border-style:solid;border-width:1px;padding:8px}.login-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.header.quadrato-header{z-index:999}.quadrato-header-auth{align-items:center;gap:12px;display:flex}.quadrato-header-username{font-size:var(--font-size);color:#333}form{font-family:var(--font-family)}.set-password-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.set-password-modal-error{color:#d32f2f;font-size:var(--primary-font);margin:0}.sg-color-picker{font-family:var(--font-family);position:relative}.sg-color-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-family:inherit;font-size:13px;display:flex}.sg-color-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-color-picker-swatch{border:1px solid #00000026;border-radius:4px;flex:none;width:18px;height:18px}.sg-color-picker-popover{z-index:30;background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);box-shadow:var(--shadow-1);width:170px;padding:10px;position:absolute;top:calc(100% + 4px);left:0}.sg-color-picker-grid{grid-template-columns:repeat(6,1fr);gap:6px;display:grid}.sg-color-picker-swatch-button{cursor:pointer;border:1px solid #00000026;border-radius:4px;width:20px;height:20px;padding:0}.sg-color-picker-swatch-button.active{border:2px solid var(--accent)}.sg-color-picker-custom{border-top:1px solid var(--input-border);color:var(--ink-muted);cursor:pointer;justify-content:space-between;align-items:center;gap:8px;margin-top:8px;padding-top:8px;font-size:11px;display:flex}.sg-color-picker-custom input[type=color]{cursor:pointer;border:none;width:26px;height:20px;padding:0}.sg-font-picker{font-family:var(--font-family);position:relative}.sg-font-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.sg-font-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-font-picker-toggle-caret{opacity:.5;flex:none;font-size:10px}.sg-font-picker-list{background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);max-height:260px;box-shadow:var(--shadow-1);z-index:30;margin:0;padding:4px 0;list-style:none;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto}.sg-font-picker-option{text-align:left;width:100%;color:inherit;cursor:pointer;background:0 0;border:none;padding:8px 10px;font-size:15px;display:block}.sg-font-picker-option.active{background:var(--accent-soft)}:root{--unit:3px;--primary-bg:#f5f5f5;--primary-border:#ccc;--radius:calc(var(--unit) * 2);--primary-radius:var(--radius);--primary-font:var(--font-size);--primary-hover-bg:#e0e0e0;--modal-bg:#fff;--modal-overlay:#0000004d;--modal-title-color:#222;--input-bg:#fff;--input-border:#ccc;--input-radius:var(--radius);--input-font:1rem;--font-size:14px;--font-family:Arial, sans-serif;--font-size-h1:calc(var(--font-size) * 1.5);--button-bg:#6f9cf7;--button-bg-hover:#5480e6;--button-color:#fff;--button-radius:999px;--button-shadow:0 1px 2px #5480e61f, 0 1px 3px #5480e61a;--button-ease-standard:cubic-bezier(.4, 0, .2, 1);--button-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--accent:#3d5fc4;--accent-strong:#2e4aa0;--accent-soft:#e2e7f8;--ink-muted:#647089;--shadow-1:0 1px 2px #0f172a14, 0 1px 3px #0f172a0f;--shadow-2:0 4px 12px #0f172a1f}.theme-dark{--primary-bg:#222;--primary-border:#444;--primary-font:1rem;--font-family:"Inter", Arial, sans-serif;--primary-hover-bg:#333;--modal-bg:#222;--modal-title-color:#fff;--input-bg:#333;--input-border:#555;--input-font:1rem;--button-bg:#6f9cf7;--button-bg-hover:#86aefc;--button-color:#fff;--accent:#6f9cf7;--accent-strong:#86aefc;--accent-soft:#6f9cf72e;--ink-muted:#9aa3b5;--shadow-1:0 1px 2px #0000004d, 0 1px 3px #0000003d;--shadow-2:0 4px 12px #0006}.sg-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family);align-items:center;gap:6px;display:flex}.sg-toggle-input{opacity:0;width:1px;height:1px;position:absolute}.sg-toggle-track{background:var(--input-border);border-radius:999px;flex:none;width:34px;height:20px;transition:background .15s cubic-bezier(.4,0,.2,1);position:relative}.sg-toggle-input:checked+.sg-toggle-track{background:var(--accent)}.sg-toggle-thumb{background:var(--input-bg);width:16px;height:16px;box-shadow:var(--shadow-1);border-radius:50%;transition:left .15s cubic-bezier(.4,0,.2,1);position:absolute;top:2px;left:2px}.sg-toggle-input:checked+.sg-toggle-track .sg-toggle-thumb{left:16px}.sg-toggle-input:focus-visible+.sg-toggle-track{outline:2px solid var(--accent-strong);outline-offset:2px}.sg-toggle-label{color:var(--ink-muted);white-space:nowrap;font-size:13px}
1
+ .custom-button{border-radius:var(--button-radius);background:var(--button-bg);color:var(--button-color);cursor:pointer;font-size:var(--primary-font);font-weight:600;font-family:var(--font-family);box-shadow:var(--button-shadow);transition:background .15s var(--button-ease-standard), transform var(--button-ease-bounce) .2s;border:none;padding:8px 20px}.custom-button:hover:not(:disabled){background:var(--button-bg-hover);transform:translateY(-1px)}.custom-button:active:not(:disabled){transform:scale(.97)}.custom-button:disabled{opacity:.6;cursor:default}.custom-button-with-icon{align-items:center;gap:8px;display:inline-flex}.custom-button-label-visually-hidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.sg-icon{vertical-align:middle;flex-shrink:0;display:inline-block}.footer{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;justify-content:space-between;align-items:center;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.footer a{color:#1ea7fd;text-decoration:none}.footer a:hover{text-decoration:underline}.cookie-consent{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;z-index:1000;box-sizing:border-box;flex-wrap:wrap;justify-content:center;align-items:center;gap:16px;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.cookie-consent-text{flex:320px;margin:0}.cookie-consent a{color:#1ea7fd;text-decoration:none}.cookie-consent a:hover{text-decoration:underline}.cookie-consent-accept{flex:none}.logo-text{font-size:var(--font-size-h1);font-family:var(--font-family);margin:0;font-weight:400}.header{z-index:100;width:100%;font-size:var(--font-size);background-color:#fff;border-bottom:1px solid #e1e5e9;position:sticky;top:0;box-shadow:0 2px 4px #0000001a}.header-container{justify-content:flex-start;align-items:center;max-width:1200px;margin:0 auto;padding:16px;display:flex}.header-actions{align-items:center;gap:12px;margin-left:auto;display:flex}.logo{cursor:pointer;color:#333;font-size:24px;font-weight:700;transition:color .2s}.logo:hover{color:#007acc}.logo-full{display:inline}.logo-short{display:none}@media (width<=768px){.header-container{padding:12px 16px}.logo{font-size:var(--font-size)}.logo-full{display:none}.logo-short{display:inline}}@media (width<=480px){.header-container{padding:8px 12px}.logo{font-size:var(--font-size)}}.sg-app-launcher{font-family:var(--font-family);position:relative}.sg-app-launcher-toggle{width:40px;height:40px;color:var(--ink-muted);cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;display:inline-flex}.sg-app-launcher-toggle:hover,.sg-app-launcher-toggle[aria-expanded=true]{background:var(--primary-hover-bg)}.sg-app-launcher-panel{z-index:1000;box-sizing:border-box;border:1px solid var(--primary-border);border-radius:calc(var(--radius) * 3);background:var(--modal-bg);width:320px;max-width:calc(100vw - 24px);max-height:70vh;box-shadow:var(--shadow-2);padding:12px;position:absolute;top:calc(100% + 8px);right:0;overflow-y:auto}.sg-app-launcher-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;margin:0;padding:0;list-style:none;display:grid}.sg-app-launcher-app{border-radius:var(--radius);color:inherit;flex-direction:column;align-items:center;gap:6px;padding:12px 4px;text-decoration:none;display:flex}.sg-app-launcher-app:hover,.sg-app-launcher-app:focus-visible{background:var(--primary-hover-bg)}.sg-app-launcher-app.current{background:var(--accent-soft)}.sg-app-launcher-tile{border-radius:var(--radius);background:var(--accent);color:#fff;justify-content:center;align-items:center;width:40px;height:40px;font-size:18px;font-weight:600;display:flex}.sg-app-launcher-name{text-overflow:ellipsis;white-space:nowrap;max-width:100%;font-size:13px;overflow:hidden}.sg-app-launcher-message{color:var(--ink-muted);margin:0;padding:8px;font-size:13px}.sg-authenticator-button{font-size:.9rem;font-family:var(--font-family);border:1px solid var(--primary-border);border-radius:var(--radius);background:var(--primary-bg);color:#333;cursor:pointer;padding:.4rem 1rem;transition:background .15s,border-color .15s}.sg-authenticator-button:hover{background:var(--primary-hover-bg);border-color:var(--ink-muted)}.modal-overlay{background:var(--modal-overlay);z-index:1000;justify-content:center;align-items:center;width:100vw;height:100vh;animation:.25s ease-out sg-modal-overlay-fade-in;display:flex;position:fixed;top:0;left:0}.modal-overlay.modal-overlay-closing{animation:.22s ease-in forwards sg-modal-overlay-fade-out}.modal-content{--drag-x:0px;--drag-y:0px;background:var(--modal-bg);border-radius:var(--primary-radius);font-size:var(--primary-font);min-width:320px;max-width:calc(100vw - 40px);max-height:90vh;transform:translate(var(--drag-x), var(--drag-y));flex-direction:column;animation:.3s ease-out sg-modal-slide-in;display:flex;overflow:hidden;box-shadow:0 2px 16px #00000026}.modal-content.modal-content-closing{animation:.22s ease-in forwards sg-modal-slide-out}@keyframes sg-modal-overlay-fade-in{0%{opacity:0}to{opacity:1}}@keyframes sg-modal-overlay-fade-out{0%{opacity:1}to{opacity:0}}@keyframes sg-modal-slide-in{0%{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}to{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}}@keyframes sg-modal-slide-out{0%{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}to{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}}.modal-header{background:var(--primary-bg);border-top-left-radius:var(--primary-radius);border-top-right-radius:var(--primary-radius);cursor:grab;touch-action:none;flex:none;align-items:center;gap:8px;padding:16px;display:flex}.modal-header-dragging{cursor:grabbing;-webkit-user-select:none;user-select:none}.modal-icon{color:var(--modal-title-color);display:inline-flex}.modal-title{color:var(--modal-title-color);font-family:var(--font-family);font-size:var(--primary-font);flex:1;margin:0}.modal-close{cursor:pointer;color:var(--modal-title-color);background:0 0;border:none;padding:4px 8px;font-size:20px;line-height:1}.modal-close:disabled{cursor:default;opacity:.6}.modal-children{font-family:var(--font-family);padding:16px;overflow-y:auto}.modal-footer{border-top:1px solid var(--primary-border);flex-wrap:wrap;flex:none;justify-content:flex-end;gap:8px;padding:12px 16px;display:flex}.input-label{font-weight:500;font-family:var(--font-family);font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field--invalid{background-color:#ffe5e5;border-color:#c00}.input-wrapper{margin-bottom:16px}.input-label{font-weight:500;font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field{box-sizing:border-box;border-radius:var(--radius);width:100%;font-size:var(--primary-font);border-style:solid;border-width:1px;padding:8px}.login-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.header.quadrato-header{z-index:999}.quadrato-header-auth{align-items:center;gap:12px;display:flex}.quadrato-header-username{font-size:var(--font-size);color:#333;transition:color .2s}.quadrato-header-username:hover{color:var(--accent)}form{font-family:var(--font-family)}.set-password-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.set-password-modal-error{color:#d32f2f;font-size:var(--primary-font);margin:0}.sg-color-picker{font-family:var(--font-family);position:relative}.sg-color-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-family:inherit;font-size:13px;display:flex}.sg-color-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-color-picker-swatch{border:1px solid #00000026;border-radius:4px;flex:none;width:18px;height:18px}.sg-color-picker-popover{z-index:30;background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);box-shadow:var(--shadow-1);width:170px;padding:10px;position:absolute;top:calc(100% + 4px);left:0}.sg-color-picker-grid{grid-template-columns:repeat(6,1fr);gap:6px;display:grid}.sg-color-picker-swatch-button{cursor:pointer;border:1px solid #00000026;border-radius:4px;width:20px;height:20px;padding:0}.sg-color-picker-swatch-button.active{border:2px solid var(--accent)}.sg-color-picker-custom{border-top:1px solid var(--input-border);color:var(--ink-muted);cursor:pointer;justify-content:space-between;align-items:center;gap:8px;margin-top:8px;padding-top:8px;font-size:11px;display:flex}.sg-color-picker-custom input[type=color]{cursor:pointer;border:none;width:26px;height:20px;padding:0}.sg-font-picker{font-family:var(--font-family);position:relative}.sg-font-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.sg-font-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-font-picker-toggle-caret{opacity:.5;flex:none;font-size:10px}.sg-font-picker-list{background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);max-height:260px;box-shadow:var(--shadow-1);z-index:30;margin:0;padding:4px 0;list-style:none;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto}.sg-font-picker-option{text-align:left;width:100%;color:inherit;cursor:pointer;background:0 0;border:none;padding:8px 10px;font-size:15px;display:block}.sg-font-picker-option.active{background:var(--accent-soft)}:root{--unit:3px;--primary-bg:#f5f5f5;--primary-border:#ccc;--radius:calc(var(--unit) * 2);--primary-radius:var(--radius);--primary-font:var(--font-size);--primary-hover-bg:#e0e0e0;--modal-bg:#fff;--modal-overlay:#0000004d;--modal-title-color:#222;--input-bg:#fff;--input-border:#ccc;--input-radius:var(--radius);--input-font:1rem;--font-size:14px;--font-family:Arial, sans-serif;--font-size-h1:calc(var(--font-size) * 1.5);--button-bg:#6f9cf7;--button-bg-hover:#5480e6;--button-color:#fff;--button-radius:999px;--button-shadow:0 1px 2px #5480e61f, 0 1px 3px #5480e61a;--button-ease-standard:cubic-bezier(.4, 0, .2, 1);--button-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--accent:#3d5fc4;--accent-strong:#2e4aa0;--accent-soft:#e2e7f8;--ink-muted:#647089;--shadow-1:0 1px 2px #0f172a14, 0 1px 3px #0f172a0f;--shadow-2:0 4px 12px #0f172a1f}.theme-dark{--primary-bg:#222;--primary-border:#444;--primary-font:1rem;--font-family:"Inter", Arial, sans-serif;--primary-hover-bg:#333;--modal-bg:#222;--modal-title-color:#fff;--input-bg:#333;--input-border:#555;--input-font:1rem;--button-bg:#6f9cf7;--button-bg-hover:#86aefc;--button-color:#fff;--accent:#6f9cf7;--accent-strong:#86aefc;--accent-soft:#6f9cf72e;--ink-muted:#9aa3b5;--shadow-1:0 1px 2px #0000004d, 0 1px 3px #0000003d;--shadow-2:0 4px 12px #0006}.sg-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family);align-items:center;gap:6px;display:flex}.sg-toggle-input{opacity:0;width:1px;height:1px;position:absolute}.sg-toggle-track{background:var(--input-border);border-radius:999px;flex:none;width:34px;height:20px;transition:background .15s cubic-bezier(.4,0,.2,1);position:relative}.sg-toggle-input:checked+.sg-toggle-track{background:var(--accent)}.sg-toggle-thumb{background:var(--input-bg);width:16px;height:16px;box-shadow:var(--shadow-1);border-radius:50%;transition:left .15s cubic-bezier(.4,0,.2,1);position:absolute;top:2px;left:2px}.sg-toggle-input:checked+.sg-toggle-track .sg-toggle-thumb{left:16px}.sg-toggle-input:focus-visible+.sg-toggle-track{outline:2px solid var(--accent-strong);outline-offset:2px}.sg-toggle-label{color:var(--ink-muted);white-space:nowrap;font-size:13px}
2
2
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sensorario/sg-components",
3
- "version": "0.0.99",
3
+ "version": "0.0.101",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "scripts": {