@malto/sdk 0.1.1 → 0.1.2

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
@@ -178,10 +178,12 @@ function upsert(id, css) {
178
178
  function buildCss(opts) {
179
179
  const primary = opts.primary;
180
180
  const tones = derivePalette(primary);
181
- const radiusScale = opts.radius === "sm" ? "10px" : opts.radius === "lg" ? "22px" : "16px";
181
+ const radiusScale = opts.radius === "sm" ? "12px" : opts.radius === "lg" ? "24px" : "20px";
182
182
  const appearance = opts.appearance ?? "auto";
183
183
  const overrides = opts.cssVars ?? {};
184
184
  return `
185
+ @import url('https://fonts.googleapis.com/css2?family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700&display=swap');
186
+
185
187
  :where(.malto-root, .malto-root *) {
186
188
  box-sizing: border-box;
187
189
  }
@@ -194,21 +196,21 @@ function buildCss(opts) {
194
196
  --malto-primary-600: ${tones.shade600};
195
197
  --malto-primary-rgb: ${tones.rgb};
196
198
  --malto-surface: ${overrides.surface ?? "#ffffff"};
197
- --malto-surface-muted: ${overrides.surfaceMuted ?? "#fbfaff"};
198
- --malto-surface-elevated: rgba(255,255,255,0.85);
199
- --malto-border: ${overrides.border ?? "rgba(15, 13, 35, 0.06)"};
200
- --malto-border-strong: rgba(15, 13, 35, 0.1);
201
- --malto-text: ${overrides.text ?? "#0f0d23"};
199
+ --malto-surface-muted: ${overrides.surfaceMuted ?? "#f2eeff"};
200
+ --malto-surface-elevated: rgba(255,255,255,0.92);
201
+ --malto-border: ${overrides.border ?? "#e2e8f0"};
202
+ --malto-border-strong: #cbd1de;
203
+ --malto-text: ${overrides.text ?? "#0a0a0a"};
202
204
  --malto-text-muted: ${overrides.textMuted ?? "#5b5871"};
203
- --malto-text-subtle: rgba(15, 13, 35, 0.45);
205
+ --malto-text-subtle: rgba(10, 10, 10, 0.5);
204
206
  --malto-radius: ${overrides.radius ?? radiusScale};
205
- --malto-radius-sm: 10px;
207
+ --malto-radius-sm: 12px;
206
208
  --malto-radius-pill: 999px;
207
- --malto-shadow-sm: ${overrides.shadow ?? "0 4px 12px -4px rgba(15, 13, 35, 0.08)"};
208
- --malto-shadow-md: 0 12px 32px -8px rgba(15, 13, 35, 0.16);
209
- --malto-shadow-lg: 0 30px 60px -20px rgba(15, 13, 35, 0.28);
210
- --malto-shadow-glow: 0 12px 24px -8px rgba(var(--malto-primary-rgb), 0.45);
211
- --malto-font: ${overrides.font ?? "-apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, system-ui, sans-serif"};
209
+ --malto-shadow-sm: ${overrides.shadow ?? "0 4px 12px -6px rgba(25, 24, 56, 0.12)"};
210
+ --malto-shadow-md: 0 10px 30px -10px rgba(25, 24, 56, 0.15);
211
+ --malto-shadow-lg: 0 30px 60px -20px rgba(25, 24, 56, 0.25);
212
+ --malto-shadow-glow: 0 8px 20px -6px rgba(var(--malto-primary-rgb), 0.45);
213
+ --malto-font: ${overrides.font ?? "'Google Sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif"};
212
214
  --malto-ease-spring: cubic-bezier(0.34, 1.4, 0.5, 1);
213
215
  --malto-ease-smooth: cubic-bezier(0.32, 0.72, 0, 1);
214
216
  }
@@ -269,12 +271,12 @@ function buildCss(opts) {
269
271
 
270
272
  .malto-trigger {
271
273
  display: inline-flex; align-items: center; gap: 8px;
272
- padding: 9px 18px;
274
+ padding: 10px 20px;
273
275
  border-radius: var(--malto-radius-pill);
274
276
  background: var(--malto-primary);
275
277
  color: var(--malto-primary-contrast);
276
278
  border: none; cursor: pointer;
277
- font-size: 13px; font-weight: 600; letter-spacing: -0.01em;
279
+ font-size: 14px; font-weight: 600; letter-spacing: -0.01em;
278
280
  box-shadow: var(--malto-shadow-glow);
279
281
  transition: transform .25s var(--malto-ease-spring), box-shadow .2s ease;
280
282
  }
@@ -328,23 +330,23 @@ function buildCss(opts) {
328
330
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500 */
329
331
  .malto-header {
330
332
  display: flex; align-items: center; justify-content: space-between;
331
- padding: 18px 22px 14px;
333
+ padding: 22px 24px 16px;
332
334
  position: relative;
333
335
  flex: none;
334
336
  }
335
337
  .malto-header h3 {
336
338
  margin: 0;
337
- font-size: 16px; font-weight: 600;
339
+ font-size: 17px; font-weight: 600;
338
340
  color: var(--malto-text);
339
- letter-spacing: -0.015em;
341
+ letter-spacing: -0.02em;
340
342
  }
341
343
  .malto-header-meta {
342
344
  display: flex; align-items: center; gap: 10px;
343
345
  }
344
346
  .malto-board-logo {
345
347
  width: 28px; height: 28px;
346
- border-radius: 8px;
347
- background: var(--malto-primary-100);
348
+ border-radius: 10px;
349
+ background: var(--malto-surface-muted);
348
350
  display: flex; align-items: center; justify-content: center;
349
351
  color: var(--malto-primary);
350
352
  font-size: 12px; font-weight: 700;
@@ -362,7 +364,7 @@ function buildCss(opts) {
362
364
  transition: background .15s ease, color .15s ease;
363
365
  }
364
366
  .malto-close:hover {
365
- background: var(--malto-primary-50);
367
+ background: var(--malto-surface-muted);
366
368
  color: var(--malto-text);
367
369
  }
368
370
 
@@ -370,8 +372,8 @@ function buildCss(opts) {
370
372
  .malto-tabs {
371
373
  display: flex;
372
374
  padding: 4px;
373
- margin: 0 18px 14px;
374
- background: var(--malto-primary-50);
375
+ margin: 0 24px 16px;
376
+ background: var(--malto-surface-muted);
375
377
  border-radius: var(--malto-radius-sm);
376
378
  flex: none;
377
379
  }
@@ -397,7 +399,7 @@ function buildCss(opts) {
397
399
  .malto-body {
398
400
  flex: 1;
399
401
  overflow-y: auto;
400
- padding: 4px 18px 18px;
402
+ padding: 4px 24px 22px;
401
403
  background: var(--malto-surface);
402
404
  scroll-behavior: smooth;
403
405
  }
@@ -412,7 +414,7 @@ function buildCss(opts) {
412
414
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Feedback row \u2500\u2500\u2500\u2500\u2500\u2500 */
413
415
  .malto-item {
414
416
  display: flex; gap: 12px;
415
- padding: 12px;
417
+ padding: 14px;
416
418
  border-radius: 12px;
417
419
  background: var(--malto-surface);
418
420
  border: 1px solid var(--malto-border);
@@ -423,15 +425,15 @@ function buildCss(opts) {
423
425
  .malto-item:hover {
424
426
  border-color: var(--malto-border-strong);
425
427
  transform: translateY(-1px);
426
- box-shadow: var(--malto-shadow-sm);
428
+ box-shadow: 0 6px 16px -8px rgba(25, 24, 56, 0.12);
427
429
  }
428
430
  .malto-vote {
429
431
  display: flex; flex-direction: column;
430
432
  align-items: center; justify-content: center;
431
433
  min-width: 44px; padding: 6px 4px;
432
- border-radius: 10px;
434
+ border-radius: 12px;
433
435
  border: 1px solid var(--malto-border);
434
- background: var(--malto-surface-muted);
436
+ background: var(--malto-surface);
435
437
  cursor: pointer;
436
438
  font-size: 11px; color: var(--malto-text-muted);
437
439
  transition: all .2s var(--malto-ease-spring);
@@ -518,10 +520,10 @@ function buildCss(opts) {
518
520
  }
519
521
  .malto-input, .malto-textarea {
520
522
  width: 100%;
521
- padding: 11px 14px;
522
- border: 1px solid var(--malto-border-strong);
523
+ padding: 12px 14px;
524
+ border: 1px solid var(--malto-border);
523
525
  border-radius: 12px;
524
- font-size: 13.5px;
526
+ font-size: 14px;
525
527
  color: var(--malto-text);
526
528
  background: var(--malto-surface);
527
529
  outline: none;
@@ -533,7 +535,7 @@ function buildCss(opts) {
533
535
  }
534
536
  .malto-input:focus, .malto-textarea:focus {
535
537
  border-color: var(--malto-primary);
536
- box-shadow: 0 0 0 4px rgba(var(--malto-primary-rgb), 0.1);
538
+ box-shadow: 0 0 0 4px rgba(var(--malto-primary-rgb), 0.12);
537
539
  }
538
540
  .malto-textarea {
539
541
  min-height: 110px;
@@ -541,13 +543,13 @@ function buildCss(opts) {
541
543
  line-height: 1.5;
542
544
  }
543
545
  .malto-button {
544
- padding: 11px 18px;
546
+ padding: 12px 20px;
545
547
  border-radius: 12px;
546
548
  background: var(--malto-primary);
547
549
  color: var(--malto-primary-contrast);
548
550
  border: none; cursor: pointer;
549
- font-size: 13px; font-weight: 600;
550
- letter-spacing: -0.005em;
551
+ font-size: 14px; font-weight: 600;
552
+ letter-spacing: -0.01em;
551
553
  box-shadow: var(--malto-shadow-glow);
552
554
  transition: transform .2s var(--malto-ease-spring), box-shadow .2s ease, opacity .2s ease;
553
555
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
@@ -556,13 +558,13 @@ function buildCss(opts) {
556
558
  .malto-button:active { transform: scale(0.97); }
557
559
  .malto-button[disabled] { opacity: .5; cursor: not-allowed; transform: none; }
558
560
  .malto-secondary {
559
- padding: 9px 14px;
560
- border-radius: 10px;
561
+ padding: 10px 16px;
562
+ border-radius: 12px;
561
563
  background: transparent;
562
564
  color: var(--malto-text);
563
- border: 1px solid var(--malto-border-strong);
565
+ border: 1px solid var(--malto-border);
564
566
  cursor: pointer;
565
- font-size: 13px; font-weight: 500;
567
+ font-size: 13.5px; font-weight: 500;
566
568
  transition: all .2s ease;
567
569
  }
568
570
  .malto-secondary:hover {
@@ -655,7 +657,7 @@ function buildCss(opts) {
655
657
 
656
658
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Releases / changelog \u2500\u2500\u2500\u2500\u2500\u2500 */
657
659
  .malto-release {
658
- padding: 14px;
660
+ padding: 16px;
659
661
  border: 1px solid var(--malto-border);
660
662
  border-radius: 12px;
661
663
  margin-bottom: 8px;
@@ -725,10 +727,10 @@ function buildCss(opts) {
725
727
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Footer banner (sign-in CTA) \u2500\u2500\u2500\u2500\u2500\u2500 */
726
728
  .malto-footer-banner {
727
729
  flex: none;
728
- padding: 12px 18px;
730
+ padding: 14px 24px;
729
731
  background: var(--malto-surface-muted);
730
732
  border-top: 1px solid var(--malto-border);
731
- font-size: 12px;
733
+ font-size: 12.5px;
732
734
  color: var(--malto-text-muted);
733
735
  display: flex; align-items: center; justify-content: space-between;
734
736
  gap: 10px;
@@ -748,7 +750,7 @@ function buildCss(opts) {
748
750
  }
749
751
  .malto-back:hover {
750
752
  color: var(--malto-text);
751
- background: var(--malto-primary-50);
753
+ background: var(--malto-surface-muted);
752
754
  }
753
755
 
754
756
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Animations \u2500\u2500\u2500\u2500\u2500\u2500 */
package/dist/index.js CHANGED
@@ -176,10 +176,12 @@ function upsert(id, css) {
176
176
  function buildCss(opts) {
177
177
  const primary = opts.primary;
178
178
  const tones = derivePalette(primary);
179
- const radiusScale = opts.radius === "sm" ? "10px" : opts.radius === "lg" ? "22px" : "16px";
179
+ const radiusScale = opts.radius === "sm" ? "12px" : opts.radius === "lg" ? "24px" : "20px";
180
180
  const appearance = opts.appearance ?? "auto";
181
181
  const overrides = opts.cssVars ?? {};
182
182
  return `
183
+ @import url('https://fonts.googleapis.com/css2?family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700&display=swap');
184
+
183
185
  :where(.malto-root, .malto-root *) {
184
186
  box-sizing: border-box;
185
187
  }
@@ -192,21 +194,21 @@ function buildCss(opts) {
192
194
  --malto-primary-600: ${tones.shade600};
193
195
  --malto-primary-rgb: ${tones.rgb};
194
196
  --malto-surface: ${overrides.surface ?? "#ffffff"};
195
- --malto-surface-muted: ${overrides.surfaceMuted ?? "#fbfaff"};
196
- --malto-surface-elevated: rgba(255,255,255,0.85);
197
- --malto-border: ${overrides.border ?? "rgba(15, 13, 35, 0.06)"};
198
- --malto-border-strong: rgba(15, 13, 35, 0.1);
199
- --malto-text: ${overrides.text ?? "#0f0d23"};
197
+ --malto-surface-muted: ${overrides.surfaceMuted ?? "#f2eeff"};
198
+ --malto-surface-elevated: rgba(255,255,255,0.92);
199
+ --malto-border: ${overrides.border ?? "#e2e8f0"};
200
+ --malto-border-strong: #cbd1de;
201
+ --malto-text: ${overrides.text ?? "#0a0a0a"};
200
202
  --malto-text-muted: ${overrides.textMuted ?? "#5b5871"};
201
- --malto-text-subtle: rgba(15, 13, 35, 0.45);
203
+ --malto-text-subtle: rgba(10, 10, 10, 0.5);
202
204
  --malto-radius: ${overrides.radius ?? radiusScale};
203
- --malto-radius-sm: 10px;
205
+ --malto-radius-sm: 12px;
204
206
  --malto-radius-pill: 999px;
205
- --malto-shadow-sm: ${overrides.shadow ?? "0 4px 12px -4px rgba(15, 13, 35, 0.08)"};
206
- --malto-shadow-md: 0 12px 32px -8px rgba(15, 13, 35, 0.16);
207
- --malto-shadow-lg: 0 30px 60px -20px rgba(15, 13, 35, 0.28);
208
- --malto-shadow-glow: 0 12px 24px -8px rgba(var(--malto-primary-rgb), 0.45);
209
- --malto-font: ${overrides.font ?? "-apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, system-ui, sans-serif"};
207
+ --malto-shadow-sm: ${overrides.shadow ?? "0 4px 12px -6px rgba(25, 24, 56, 0.12)"};
208
+ --malto-shadow-md: 0 10px 30px -10px rgba(25, 24, 56, 0.15);
209
+ --malto-shadow-lg: 0 30px 60px -20px rgba(25, 24, 56, 0.25);
210
+ --malto-shadow-glow: 0 8px 20px -6px rgba(var(--malto-primary-rgb), 0.45);
211
+ --malto-font: ${overrides.font ?? "'Google Sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif"};
210
212
  --malto-ease-spring: cubic-bezier(0.34, 1.4, 0.5, 1);
211
213
  --malto-ease-smooth: cubic-bezier(0.32, 0.72, 0, 1);
212
214
  }
@@ -267,12 +269,12 @@ function buildCss(opts) {
267
269
 
268
270
  .malto-trigger {
269
271
  display: inline-flex; align-items: center; gap: 8px;
270
- padding: 9px 18px;
272
+ padding: 10px 20px;
271
273
  border-radius: var(--malto-radius-pill);
272
274
  background: var(--malto-primary);
273
275
  color: var(--malto-primary-contrast);
274
276
  border: none; cursor: pointer;
275
- font-size: 13px; font-weight: 600; letter-spacing: -0.01em;
277
+ font-size: 14px; font-weight: 600; letter-spacing: -0.01em;
276
278
  box-shadow: var(--malto-shadow-glow);
277
279
  transition: transform .25s var(--malto-ease-spring), box-shadow .2s ease;
278
280
  }
@@ -326,23 +328,23 @@ function buildCss(opts) {
326
328
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500 */
327
329
  .malto-header {
328
330
  display: flex; align-items: center; justify-content: space-between;
329
- padding: 18px 22px 14px;
331
+ padding: 22px 24px 16px;
330
332
  position: relative;
331
333
  flex: none;
332
334
  }
333
335
  .malto-header h3 {
334
336
  margin: 0;
335
- font-size: 16px; font-weight: 600;
337
+ font-size: 17px; font-weight: 600;
336
338
  color: var(--malto-text);
337
- letter-spacing: -0.015em;
339
+ letter-spacing: -0.02em;
338
340
  }
339
341
  .malto-header-meta {
340
342
  display: flex; align-items: center; gap: 10px;
341
343
  }
342
344
  .malto-board-logo {
343
345
  width: 28px; height: 28px;
344
- border-radius: 8px;
345
- background: var(--malto-primary-100);
346
+ border-radius: 10px;
347
+ background: var(--malto-surface-muted);
346
348
  display: flex; align-items: center; justify-content: center;
347
349
  color: var(--malto-primary);
348
350
  font-size: 12px; font-weight: 700;
@@ -360,7 +362,7 @@ function buildCss(opts) {
360
362
  transition: background .15s ease, color .15s ease;
361
363
  }
362
364
  .malto-close:hover {
363
- background: var(--malto-primary-50);
365
+ background: var(--malto-surface-muted);
364
366
  color: var(--malto-text);
365
367
  }
366
368
 
@@ -368,8 +370,8 @@ function buildCss(opts) {
368
370
  .malto-tabs {
369
371
  display: flex;
370
372
  padding: 4px;
371
- margin: 0 18px 14px;
372
- background: var(--malto-primary-50);
373
+ margin: 0 24px 16px;
374
+ background: var(--malto-surface-muted);
373
375
  border-radius: var(--malto-radius-sm);
374
376
  flex: none;
375
377
  }
@@ -395,7 +397,7 @@ function buildCss(opts) {
395
397
  .malto-body {
396
398
  flex: 1;
397
399
  overflow-y: auto;
398
- padding: 4px 18px 18px;
400
+ padding: 4px 24px 22px;
399
401
  background: var(--malto-surface);
400
402
  scroll-behavior: smooth;
401
403
  }
@@ -410,7 +412,7 @@ function buildCss(opts) {
410
412
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Feedback row \u2500\u2500\u2500\u2500\u2500\u2500 */
411
413
  .malto-item {
412
414
  display: flex; gap: 12px;
413
- padding: 12px;
415
+ padding: 14px;
414
416
  border-radius: 12px;
415
417
  background: var(--malto-surface);
416
418
  border: 1px solid var(--malto-border);
@@ -421,15 +423,15 @@ function buildCss(opts) {
421
423
  .malto-item:hover {
422
424
  border-color: var(--malto-border-strong);
423
425
  transform: translateY(-1px);
424
- box-shadow: var(--malto-shadow-sm);
426
+ box-shadow: 0 6px 16px -8px rgba(25, 24, 56, 0.12);
425
427
  }
426
428
  .malto-vote {
427
429
  display: flex; flex-direction: column;
428
430
  align-items: center; justify-content: center;
429
431
  min-width: 44px; padding: 6px 4px;
430
- border-radius: 10px;
432
+ border-radius: 12px;
431
433
  border: 1px solid var(--malto-border);
432
- background: var(--malto-surface-muted);
434
+ background: var(--malto-surface);
433
435
  cursor: pointer;
434
436
  font-size: 11px; color: var(--malto-text-muted);
435
437
  transition: all .2s var(--malto-ease-spring);
@@ -516,10 +518,10 @@ function buildCss(opts) {
516
518
  }
517
519
  .malto-input, .malto-textarea {
518
520
  width: 100%;
519
- padding: 11px 14px;
520
- border: 1px solid var(--malto-border-strong);
521
+ padding: 12px 14px;
522
+ border: 1px solid var(--malto-border);
521
523
  border-radius: 12px;
522
- font-size: 13.5px;
524
+ font-size: 14px;
523
525
  color: var(--malto-text);
524
526
  background: var(--malto-surface);
525
527
  outline: none;
@@ -531,7 +533,7 @@ function buildCss(opts) {
531
533
  }
532
534
  .malto-input:focus, .malto-textarea:focus {
533
535
  border-color: var(--malto-primary);
534
- box-shadow: 0 0 0 4px rgba(var(--malto-primary-rgb), 0.1);
536
+ box-shadow: 0 0 0 4px rgba(var(--malto-primary-rgb), 0.12);
535
537
  }
536
538
  .malto-textarea {
537
539
  min-height: 110px;
@@ -539,13 +541,13 @@ function buildCss(opts) {
539
541
  line-height: 1.5;
540
542
  }
541
543
  .malto-button {
542
- padding: 11px 18px;
544
+ padding: 12px 20px;
543
545
  border-radius: 12px;
544
546
  background: var(--malto-primary);
545
547
  color: var(--malto-primary-contrast);
546
548
  border: none; cursor: pointer;
547
- font-size: 13px; font-weight: 600;
548
- letter-spacing: -0.005em;
549
+ font-size: 14px; font-weight: 600;
550
+ letter-spacing: -0.01em;
549
551
  box-shadow: var(--malto-shadow-glow);
550
552
  transition: transform .2s var(--malto-ease-spring), box-shadow .2s ease, opacity .2s ease;
551
553
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
@@ -554,13 +556,13 @@ function buildCss(opts) {
554
556
  .malto-button:active { transform: scale(0.97); }
555
557
  .malto-button[disabled] { opacity: .5; cursor: not-allowed; transform: none; }
556
558
  .malto-secondary {
557
- padding: 9px 14px;
558
- border-radius: 10px;
559
+ padding: 10px 16px;
560
+ border-radius: 12px;
559
561
  background: transparent;
560
562
  color: var(--malto-text);
561
- border: 1px solid var(--malto-border-strong);
563
+ border: 1px solid var(--malto-border);
562
564
  cursor: pointer;
563
- font-size: 13px; font-weight: 500;
565
+ font-size: 13.5px; font-weight: 500;
564
566
  transition: all .2s ease;
565
567
  }
566
568
  .malto-secondary:hover {
@@ -653,7 +655,7 @@ function buildCss(opts) {
653
655
 
654
656
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Releases / changelog \u2500\u2500\u2500\u2500\u2500\u2500 */
655
657
  .malto-release {
656
- padding: 14px;
658
+ padding: 16px;
657
659
  border: 1px solid var(--malto-border);
658
660
  border-radius: 12px;
659
661
  margin-bottom: 8px;
@@ -723,10 +725,10 @@ function buildCss(opts) {
723
725
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Footer banner (sign-in CTA) \u2500\u2500\u2500\u2500\u2500\u2500 */
724
726
  .malto-footer-banner {
725
727
  flex: none;
726
- padding: 12px 18px;
728
+ padding: 14px 24px;
727
729
  background: var(--malto-surface-muted);
728
730
  border-top: 1px solid var(--malto-border);
729
- font-size: 12px;
731
+ font-size: 12.5px;
730
732
  color: var(--malto-text-muted);
731
733
  display: flex; align-items: center; justify-content: space-between;
732
734
  gap: 10px;
@@ -746,7 +748,7 @@ function buildCss(opts) {
746
748
  }
747
749
  .malto-back:hover {
748
750
  color: var(--malto-text);
749
- background: var(--malto-primary-50);
751
+ background: var(--malto-surface-muted);
750
752
  }
751
753
 
752
754
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Animations \u2500\u2500\u2500\u2500\u2500\u2500 */
package/dist/malto.umd.js CHANGED
@@ -1,37 +1,39 @@
1
- var Malto=(function(exports){'use strict';var F="https://malto-api-production.up.railway.app",h=class{constructor(t){this.apiKey=t.apiKey,this.apiUrl=(t.apiUrl??F).replace(/\/$/,""),this.getSessionToken=t.getSessionToken;}async request(t,e={}){let a={"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`};if(e.headers){let s=e.headers;for(let[d,l]of Object.entries(s))a[d]=l;}if(e.auth){let s=this.getSessionToken();s&&(a["X-Malto-Session"]=s);}let o=await fetch(`${this.apiUrl}${t}`,{...e,headers:a}),r=await o.text(),n=r?A(r):null;if(!o.ok){let s=n&&(n.message||n.error)||`Request failed (${o.status})`;throw new b(Array.isArray(s)?s.join(", "):String(s),o.status)}return n}board(){return this.request("/v1/sdk/board")}listFeedbacks(){return this.request("/v1/sdk/feedbacks",{auth:true})}feedback(t){return this.request(`/v1/sdk/feedbacks/${t}`,{auth:true})}createFeedback(t){return this.request("/v1/sdk/feedbacks",{method:"POST",auth:true,body:JSON.stringify(t)})}vote(t){return this.request(`/v1/sdk/feedbacks/${t}/vote`,{method:"POST",auth:true})}comments(t){return this.request(`/v1/sdk/feedbacks/${t}/comments`,{auth:true})}addComment(t,e,a){return this.request(`/v1/sdk/feedbacks/${t}/comments`,{method:"POST",auth:true,body:JSON.stringify({body:e,parentId:a})})}roadmap(){return this.request("/v1/sdk/roadmap")}releases(){return this.request("/v1/sdk/releases")}startMagicLink(t){return this.request("/v1/sdk/auth/magic-link",{method:"POST",body:JSON.stringify(t)})}verifyMagicLink(t){return this.request("/v1/sdk/auth/verify",{method:"POST",body:JSON.stringify({token:t})})}identify(t){return this.request("/v1/sdk/auth/identify",{method:"POST",body:JSON.stringify(t)})}},b=class extends Error{constructor(e,a){super(e);this.status=a;this.name="MaltoApiError";}};function A(i){try{return JSON.parse(i)}catch{return null}}var x="malto:session:";function E(i){if(typeof window>"u")return null;try{let t=window.localStorage.getItem(x+i);if(!t)return null;let e=JSON.parse(t);return !e?.token||!e?.expiresAt?null:new Date(e.expiresAt).getTime()<Date.now()?(window.localStorage.removeItem(x+i),null):e}catch{return null}}function S(i,t){if(!(typeof window>"u"))try{window.localStorage.setItem(x+i,JSON.stringify(t));}catch{}}function g(i){if(!(typeof window>"u"))try{window.localStorage.removeItem(x+i);}catch{}}var H="malto-sdk-styles",P="malto-sdk-styles-custom";function R(i){if(typeof document>"u")return;let t=B(i);I(H,t),i.customCss?I(P,O(i.customCss)):document.getElementById(P)?.remove();}function O(i){return i.replace(/<\/style/gi,"<\\/style").replace(/<\/script/gi,"<\\/script").replace(/expression\s*\(/gi,"expr\\(").replace(/javascript\s*:/gi,"javascript\\:")}function I(i,t){let e=document.getElementById(i);if(e){e.textContent=t;return}let a=document.createElement("style");a.id=i,a.textContent=t,document.head.appendChild(a);}function B(i){let t=i.primary,e=D(t),a=i.radius==="sm"?"10px":i.radius==="lg"?"22px":"16px",o=i.appearance??"auto",r=i.cssVars??{};return `
1
+ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up.railway.app",h=class{constructor(t){this.apiKey=t.apiKey,this.apiUrl=(t.apiUrl??F).replace(/\/$/,""),this.getSessionToken=t.getSessionToken;}async request(t,e={}){let a={"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`};if(e.headers){let s=e.headers;for(let[d,l]of Object.entries(s))a[d]=l;}if(e.auth){let s=this.getSessionToken();s&&(a["X-Malto-Session"]=s);}let r=await fetch(`${this.apiUrl}${t}`,{...e,headers:a}),o=await r.text(),n=o?A(o):null;if(!r.ok){let s=n&&(n.message||n.error)||`Request failed (${r.status})`;throw new b(Array.isArray(s)?s.join(", "):String(s),r.status)}return n}board(){return this.request("/v1/sdk/board")}listFeedbacks(){return this.request("/v1/sdk/feedbacks",{auth:true})}feedback(t){return this.request(`/v1/sdk/feedbacks/${t}`,{auth:true})}createFeedback(t){return this.request("/v1/sdk/feedbacks",{method:"POST",auth:true,body:JSON.stringify(t)})}vote(t){return this.request(`/v1/sdk/feedbacks/${t}/vote`,{method:"POST",auth:true})}comments(t){return this.request(`/v1/sdk/feedbacks/${t}/comments`,{auth:true})}addComment(t,e,a){return this.request(`/v1/sdk/feedbacks/${t}/comments`,{method:"POST",auth:true,body:JSON.stringify({body:e,parentId:a})})}roadmap(){return this.request("/v1/sdk/roadmap")}releases(){return this.request("/v1/sdk/releases")}startMagicLink(t){return this.request("/v1/sdk/auth/magic-link",{method:"POST",body:JSON.stringify(t)})}verifyMagicLink(t){return this.request("/v1/sdk/auth/verify",{method:"POST",body:JSON.stringify({token:t})})}identify(t){return this.request("/v1/sdk/auth/identify",{method:"POST",body:JSON.stringify(t)})}},b=class extends Error{constructor(e,a){super(e);this.status=a;this.name="MaltoApiError";}};function A(i){try{return JSON.parse(i)}catch{return null}}var x="malto:session:";function E(i){if(typeof window>"u")return null;try{let t=window.localStorage.getItem(x+i);if(!t)return null;let e=JSON.parse(t);return !e?.token||!e?.expiresAt?null:new Date(e.expiresAt).getTime()<Date.now()?(window.localStorage.removeItem(x+i),null):e}catch{return null}}function S(i,t){if(!(typeof window>"u"))try{window.localStorage.setItem(x+i,JSON.stringify(t));}catch{}}function g(i){if(!(typeof window>"u"))try{window.localStorage.removeItem(x+i);}catch{}}var H="malto-sdk-styles",P="malto-sdk-styles-custom";function z(i){if(typeof document>"u")return;let t=B(i);I(H,t),i.customCss?I(P,O(i.customCss)):document.getElementById(P)?.remove();}function O(i){return i.replace(/<\/style/gi,"<\\/style").replace(/<\/script/gi,"<\\/script").replace(/expression\s*\(/gi,"expr\\(").replace(/javascript\s*:/gi,"javascript\\:")}function I(i,t){let e=document.getElementById(i);if(e){e.textContent=t;return}let a=document.createElement("style");a.id=i,a.textContent=t,document.head.appendChild(a);}function B(i){let t=i.primary,e=D(t),a=i.radius==="sm"?"12px":i.radius==="lg"?"24px":"20px",r=i.appearance??"auto",o=i.cssVars??{};return `
2
+ @import url('https://fonts.googleapis.com/css2?family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700&display=swap');
3
+
2
4
  :where(.malto-root, .malto-root *) {
3
5
  box-sizing: border-box;
4
6
  }
5
7
  .malto-root {
6
- --malto-primary: ${r.primary??t};
7
- --malto-primary-contrast: ${r.primaryContrast??e.contrast};
8
+ --malto-primary: ${o.primary??t};
9
+ --malto-primary-contrast: ${o.primaryContrast??e.contrast};
8
10
  --malto-primary-50: ${e.tint50};
9
11
  --malto-primary-100: ${e.tint100};
10
12
  --malto-primary-200: ${e.tint200};
11
13
  --malto-primary-600: ${e.shade600};
12
14
  --malto-primary-rgb: ${e.rgb};
13
- --malto-surface: ${r.surface??"#ffffff"};
14
- --malto-surface-muted: ${r.surfaceMuted??"#fbfaff"};
15
- --malto-surface-elevated: rgba(255,255,255,0.85);
16
- --malto-border: ${r.border??"rgba(15, 13, 35, 0.06)"};
17
- --malto-border-strong: rgba(15, 13, 35, 0.1);
18
- --malto-text: ${r.text??"#0f0d23"};
19
- --malto-text-muted: ${r.textMuted??"#5b5871"};
20
- --malto-text-subtle: rgba(15, 13, 35, 0.45);
21
- --malto-radius: ${r.radius??a};
22
- --malto-radius-sm: 10px;
15
+ --malto-surface: ${o.surface??"#ffffff"};
16
+ --malto-surface-muted: ${o.surfaceMuted??"#f2eeff"};
17
+ --malto-surface-elevated: rgba(255,255,255,0.92);
18
+ --malto-border: ${o.border??"#e2e8f0"};
19
+ --malto-border-strong: #cbd1de;
20
+ --malto-text: ${o.text??"#0a0a0a"};
21
+ --malto-text-muted: ${o.textMuted??"#5b5871"};
22
+ --malto-text-subtle: rgba(10, 10, 10, 0.5);
23
+ --malto-radius: ${o.radius??a};
24
+ --malto-radius-sm: 12px;
23
25
  --malto-radius-pill: 999px;
24
- --malto-shadow-sm: ${r.shadow??"0 4px 12px -4px rgba(15, 13, 35, 0.08)"};
25
- --malto-shadow-md: 0 12px 32px -8px rgba(15, 13, 35, 0.16);
26
- --malto-shadow-lg: 0 30px 60px -20px rgba(15, 13, 35, 0.28);
27
- --malto-shadow-glow: 0 12px 24px -8px rgba(var(--malto-primary-rgb), 0.45);
28
- --malto-font: ${r.font??"-apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, system-ui, sans-serif"};
26
+ --malto-shadow-sm: ${o.shadow??"0 4px 12px -6px rgba(25, 24, 56, 0.12)"};
27
+ --malto-shadow-md: 0 10px 30px -10px rgba(25, 24, 56, 0.15);
28
+ --malto-shadow-lg: 0 30px 60px -20px rgba(25, 24, 56, 0.25);
29
+ --malto-shadow-glow: 0 8px 20px -6px rgba(var(--malto-primary-rgb), 0.45);
30
+ --malto-font: ${o.font??"'Google Sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif"};
29
31
  --malto-ease-spring: cubic-bezier(0.34, 1.4, 0.5, 1);
30
32
  --malto-ease-smooth: cubic-bezier(0.32, 0.72, 0, 1);
31
33
  }
32
34
 
33
- ${o==="dark"?T():""}
34
- ${o==="auto"?`@media (prefers-color-scheme: dark) { ${T()} }`:""}
35
+ ${r==="dark"?T():""}
36
+ ${r==="auto"?`@media (prefers-color-scheme: dark) { ${T()} }`:""}
35
37
 
36
38
  .malto-root, .malto-root *, .malto-root *::before, .malto-root *::after {
37
39
  font-family: var(--malto-font);
@@ -86,12 +88,12 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
86
88
 
87
89
  .malto-trigger {
88
90
  display: inline-flex; align-items: center; gap: 8px;
89
- padding: 9px 18px;
91
+ padding: 10px 20px;
90
92
  border-radius: var(--malto-radius-pill);
91
93
  background: var(--malto-primary);
92
94
  color: var(--malto-primary-contrast);
93
95
  border: none; cursor: pointer;
94
- font-size: 13px; font-weight: 600; letter-spacing: -0.01em;
96
+ font-size: 14px; font-weight: 600; letter-spacing: -0.01em;
95
97
  box-shadow: var(--malto-shadow-glow);
96
98
  transition: transform .25s var(--malto-ease-spring), box-shadow .2s ease;
97
99
  }
@@ -145,23 +147,23 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
145
147
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500 */
146
148
  .malto-header {
147
149
  display: flex; align-items: center; justify-content: space-between;
148
- padding: 18px 22px 14px;
150
+ padding: 22px 24px 16px;
149
151
  position: relative;
150
152
  flex: none;
151
153
  }
152
154
  .malto-header h3 {
153
155
  margin: 0;
154
- font-size: 16px; font-weight: 600;
156
+ font-size: 17px; font-weight: 600;
155
157
  color: var(--malto-text);
156
- letter-spacing: -0.015em;
158
+ letter-spacing: -0.02em;
157
159
  }
158
160
  .malto-header-meta {
159
161
  display: flex; align-items: center; gap: 10px;
160
162
  }
161
163
  .malto-board-logo {
162
164
  width: 28px; height: 28px;
163
- border-radius: 8px;
164
- background: var(--malto-primary-100);
165
+ border-radius: 10px;
166
+ background: var(--malto-surface-muted);
165
167
  display: flex; align-items: center; justify-content: center;
166
168
  color: var(--malto-primary);
167
169
  font-size: 12px; font-weight: 700;
@@ -179,7 +181,7 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
179
181
  transition: background .15s ease, color .15s ease;
180
182
  }
181
183
  .malto-close:hover {
182
- background: var(--malto-primary-50);
184
+ background: var(--malto-surface-muted);
183
185
  color: var(--malto-text);
184
186
  }
185
187
 
@@ -187,8 +189,8 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
187
189
  .malto-tabs {
188
190
  display: flex;
189
191
  padding: 4px;
190
- margin: 0 18px 14px;
191
- background: var(--malto-primary-50);
192
+ margin: 0 24px 16px;
193
+ background: var(--malto-surface-muted);
192
194
  border-radius: var(--malto-radius-sm);
193
195
  flex: none;
194
196
  }
@@ -214,7 +216,7 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
214
216
  .malto-body {
215
217
  flex: 1;
216
218
  overflow-y: auto;
217
- padding: 4px 18px 18px;
219
+ padding: 4px 24px 22px;
218
220
  background: var(--malto-surface);
219
221
  scroll-behavior: smooth;
220
222
  }
@@ -229,7 +231,7 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
229
231
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Feedback row \u2500\u2500\u2500\u2500\u2500\u2500 */
230
232
  .malto-item {
231
233
  display: flex; gap: 12px;
232
- padding: 12px;
234
+ padding: 14px;
233
235
  border-radius: 12px;
234
236
  background: var(--malto-surface);
235
237
  border: 1px solid var(--malto-border);
@@ -240,15 +242,15 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
240
242
  .malto-item:hover {
241
243
  border-color: var(--malto-border-strong);
242
244
  transform: translateY(-1px);
243
- box-shadow: var(--malto-shadow-sm);
245
+ box-shadow: 0 6px 16px -8px rgba(25, 24, 56, 0.12);
244
246
  }
245
247
  .malto-vote {
246
248
  display: flex; flex-direction: column;
247
249
  align-items: center; justify-content: center;
248
250
  min-width: 44px; padding: 6px 4px;
249
- border-radius: 10px;
251
+ border-radius: 12px;
250
252
  border: 1px solid var(--malto-border);
251
- background: var(--malto-surface-muted);
253
+ background: var(--malto-surface);
252
254
  cursor: pointer;
253
255
  font-size: 11px; color: var(--malto-text-muted);
254
256
  transition: all .2s var(--malto-ease-spring);
@@ -335,10 +337,10 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
335
337
  }
336
338
  .malto-input, .malto-textarea {
337
339
  width: 100%;
338
- padding: 11px 14px;
339
- border: 1px solid var(--malto-border-strong);
340
+ padding: 12px 14px;
341
+ border: 1px solid var(--malto-border);
340
342
  border-radius: 12px;
341
- font-size: 13.5px;
343
+ font-size: 14px;
342
344
  color: var(--malto-text);
343
345
  background: var(--malto-surface);
344
346
  outline: none;
@@ -350,7 +352,7 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
350
352
  }
351
353
  .malto-input:focus, .malto-textarea:focus {
352
354
  border-color: var(--malto-primary);
353
- box-shadow: 0 0 0 4px rgba(var(--malto-primary-rgb), 0.1);
355
+ box-shadow: 0 0 0 4px rgba(var(--malto-primary-rgb), 0.12);
354
356
  }
355
357
  .malto-textarea {
356
358
  min-height: 110px;
@@ -358,13 +360,13 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
358
360
  line-height: 1.5;
359
361
  }
360
362
  .malto-button {
361
- padding: 11px 18px;
363
+ padding: 12px 20px;
362
364
  border-radius: 12px;
363
365
  background: var(--malto-primary);
364
366
  color: var(--malto-primary-contrast);
365
367
  border: none; cursor: pointer;
366
- font-size: 13px; font-weight: 600;
367
- letter-spacing: -0.005em;
368
+ font-size: 14px; font-weight: 600;
369
+ letter-spacing: -0.01em;
368
370
  box-shadow: var(--malto-shadow-glow);
369
371
  transition: transform .2s var(--malto-ease-spring), box-shadow .2s ease, opacity .2s ease;
370
372
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
@@ -373,13 +375,13 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
373
375
  .malto-button:active { transform: scale(0.97); }
374
376
  .malto-button[disabled] { opacity: .5; cursor: not-allowed; transform: none; }
375
377
  .malto-secondary {
376
- padding: 9px 14px;
377
- border-radius: 10px;
378
+ padding: 10px 16px;
379
+ border-radius: 12px;
378
380
  background: transparent;
379
381
  color: var(--malto-text);
380
- border: 1px solid var(--malto-border-strong);
382
+ border: 1px solid var(--malto-border);
381
383
  cursor: pointer;
382
- font-size: 13px; font-weight: 500;
384
+ font-size: 13.5px; font-weight: 500;
383
385
  transition: all .2s ease;
384
386
  }
385
387
  .malto-secondary:hover {
@@ -472,7 +474,7 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
472
474
 
473
475
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Releases / changelog \u2500\u2500\u2500\u2500\u2500\u2500 */
474
476
  .malto-release {
475
- padding: 14px;
477
+ padding: 16px;
476
478
  border: 1px solid var(--malto-border);
477
479
  border-radius: 12px;
478
480
  margin-bottom: 8px;
@@ -542,10 +544,10 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
542
544
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Footer banner (sign-in CTA) \u2500\u2500\u2500\u2500\u2500\u2500 */
543
545
  .malto-footer-banner {
544
546
  flex: none;
545
- padding: 12px 18px;
547
+ padding: 14px 24px;
546
548
  background: var(--malto-surface-muted);
547
549
  border-top: 1px solid var(--malto-border);
548
- font-size: 12px;
550
+ font-size: 12.5px;
549
551
  color: var(--malto-text-muted);
550
552
  display: flex; align-items: center; justify-content: space-between;
551
553
  gap: 10px;
@@ -565,7 +567,7 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
565
567
  }
566
568
  .malto-back:hover {
567
569
  color: var(--malto-text);
568
- background: var(--malto-primary-50);
570
+ background: var(--malto-surface-muted);
569
571
  }
570
572
 
571
573
  /* \u2500\u2500\u2500\u2500\u2500\u2500 Animations \u2500\u2500\u2500\u2500\u2500\u2500 */
@@ -603,5 +605,5 @@ var Malto=(function(exports){'use strict';var F="https://malto-api-production.up
603
605
  --malto-text-muted: #a09cc7;
604
606
  --malto-text-subtle: rgba(230, 227, 245, 0.5);
605
607
  }
606
- `}function D(i){let{r:t,g:e,b:a}=U(i);return {rgb:`${t}, ${e}, ${a}`,contrast:j(t,e,a),tint50:N(t,e,a,.06),tint100:N(t,e,a,.12),tint200:N(t,e,a,.18),shade600:V(t,e,a,-0.18)}}function U(i){let t=i.trim().replace(/^#/,"");return t.length===3&&(t=t.split("").map(e=>e+e).join("")),/^[0-9a-fA-F]{6}$/.test(t)?{r:parseInt(t.slice(0,2),16),g:parseInt(t.slice(2,4),16),b:parseInt(t.slice(4,6),16)}:{r:69,g:47,b:223}}function j(i,t,e){return (.2126*i+.7152*t+.0722*e)/255>.65?"#0f0d23":"#ffffff"}function N(i,t,e,a,o){return `rgba(${i}, ${t}, ${e}, ${a})`}function V(i,t,e,a){let o=n=>Math.max(0,Math.min(255,Math.round(n+255*a))),r=n=>o(n).toString(16).padStart(2,"0");return `#${r(i)}${r(t)}${r(e)}`}var q={"bottom-right":{right:"24px",bottom:"24px"},"bottom-left":{left:"24px",bottom:"24px"},"top-right":{right:"24px",top:"24px"},"top-left":{left:"24px",top:"24px"}},v=class{constructor(t){this.resolvedMode="bubble";this.root=null;this.container=null;this.trigger=null;this.board=null;if(!t.apiKey)throw new Error("Malto: apiKey is required");this.apiKeyPrefix=t.apiKey.slice(0,16),this.config={apiKey:t.apiKey,apiUrl:t.apiUrl??"https://malto-api-production.up.railway.app",mode:t.mode??"auto",position:t.position??"bottom-right",triggerLabel:t.triggerLabel??"Feedback",primaryColor:t.primaryColor,cssVars:t.cssVars,customCss:t.customCss,radius:t.radius??"md",appearance:t.appearance??"auto",zIndex:t.zIndex??2147483600,views:t.views,identify:t.identify,target:t.target,onReady:t.onReady,onError:t.onError};let e=E(this.apiKeyPrefix);this.state={open:false,view:"list",loading:false,error:null,feedbacks:[],roadmap:{},releases:[],selectedFeedback:null,comments:[],authEmail:"",authStatus:"idle",email:e?.email??null,name:e?.name??null},this.client=new h({apiKey:this.config.apiKey,apiUrl:this.config.apiUrl,getSessionToken:()=>E(this.apiKeyPrefix)?.token??null});}async mount(){try{let t=await this.client.board();this.board=t;let e=this.config.primaryColor||t.widget.primaryColor||t.board.boardThemeColor||"#452fdf";R({primary:e,cssVars:this.config.cssVars,customCss:this.config.customCss,radius:this.config.radius,appearance:this.config.appearance}),this.resolvedMode=this.config.mode==="auto"?t.widget.defaultMode:this.config.mode,this.config.identify&&await this.runIdentify(this.config.identify),this.renderHost(this.resolvedMode),this.config.onReady?.();}catch(t){this.config.onError?.(t);}}unmount(){this.root?.parentElement?.removeChild(this.root),this.trigger?.parentElement?.removeChild(this.trigger),this.root=null,this.trigger=null,this.container=null;}open(){this.state.open=true,this.render();}close(){this.state.open=false,this.render();}setIdentify(t){if(!t){g(this.apiKeyPrefix),this.state.email=null,this.state.name=null,this.render();return}this.runIdentify(t);}async runIdentify(t){try{let e=await this.client.identify(t);S(this.apiKeyPrefix,{token:e.sessionToken,expiresAt:e.expiresAt,email:e.user.email,name:e.user.name}),this.state.email=e.user.email,this.state.name=e.user.name,this.render();}catch(e){this.config.onError?.(e);}}renderHost(t){let e=document.createElement("div");if(e.className="malto-root",e.style.setProperty("--malto-z",String(this.config.zIndex)),document.body.appendChild(e),this.root=e,t==="inline"){let a=this.resolveTarget();if(!a){this.config.onError?.(new Error("Malto: inline target not found"));return}let o=document.createElement("div");o.className="malto-root malto-inline",o.style.setProperty("--malto-z",String(this.config.zIndex)),a.appendChild(o),this.container=o,this.state.open=true,this.render();return}if(t==="bubble"){let a=this.buildBubble(),o=q[this.config.position];Object.assign(a.style,o);let r=document.createElement("div");r.className="malto-root",r.style.setProperty("--malto-z",String(this.config.zIndex)),r.appendChild(a),document.body.appendChild(r),this.trigger=r;}else if(t==="trigger"){let a=this.resolveTarget();if(!a){this.config.onError?.(new Error("Malto: trigger target not found"));return}let o=document.createElement("span");o.className="malto-root",o.style.setProperty("--malto-z",String(this.config.zIndex));let r=document.createElement("button");r.className="malto-trigger",r.innerHTML=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg><span>${L(this.config.triggerLabel)}</span>`,r.addEventListener("click",()=>this.open()),o.appendChild(r),a.appendChild(o),this.trigger=o;}else t==="modal"&&(this.state.open=true);this.render();}buildBubble(){let t=document.createElement("button");return t.className="malto-bubble",t.setAttribute("aria-label",this.config.triggerLabel),t.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',t.addEventListener("click",()=>{this.state.open?this.close():this.open();}),t}resolveTarget(){return this.config.target?typeof this.config.target=="string"?document.querySelector(this.config.target):this.config.target:null}render(){if(!this.root)return;if(this.resolvedMode==="inline"){if(!this.container)return;this.container.innerHTML="",this.container.appendChild(this.buildPanelBody());return}if(this.root.innerHTML="",!this.state.open)return;let t=document.createElement("div");t.className="malto-overlay",t.addEventListener("click",a=>{a.target===t&&this.close();});let e=document.createElement("div");e.className="malto-modal",e.appendChild(this.buildPanelBody()),t.appendChild(e),this.root.appendChild(t);}buildPanelBody(){let t=document.createElement("div");t.style.display="flex",t.style.flexDirection="column",t.style.height="100%",t.style.minHeight="0",t.appendChild(this.buildHeader()),t.appendChild(this.buildTabs());let e=document.createElement("div");if(e.className="malto-body",e.appendChild(this.buildView()),t.appendChild(e),this.state.view!=="auth"&&!this.state.email){let a=document.createElement("div");a.className="malto-footer-banner";let o=document.createElement("span");o.innerHTML="Sign in to vote, comment, or submit ideas.";let r=document.createElement("button");r.className="malto-link",r.textContent="Sign in",r.addEventListener("click",()=>this.go("auth")),a.appendChild(o),a.appendChild(r),t.appendChild(a);}return t}buildHeader(){let t=document.createElement("div");t.className="malto-header";let e=document.createElement("div");e.className="malto-header-meta";let a=document.createElement("div");a.className="malto-board-logo";let o=$(this.board?.board.companyLogoUrl);if(o){let n=document.createElement("img");n.src=o,n.alt="",n.referrerPolicy="no-referrer",n.crossOrigin="anonymous",a.appendChild(n);}else a.textContent=(this.board?.board.companyName??this.board?.board.boardName??"M").charAt(0).toUpperCase();let r=document.createElement("h3");if(r.textContent=this.board?.board.boardName??this.board?.board.companyName??"Feedback",e.appendChild(a),e.appendChild(r),t.appendChild(e),this.resolvedMode!=="inline"){let n=document.createElement("button");n.className="malto-close",n.setAttribute("aria-label","Close"),n.innerHTML='<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',n.addEventListener("click",()=>this.close()),t.appendChild(n);}return t}buildTabs(){let t=document.createElement("div");t.className="malto-tabs";let e=this.allowedViews();return e.includes("list")&&t.appendChild(this.tabBtn("Feed","list")),e.includes("submit")&&t.appendChild(this.tabBtn("New","submit")),e.includes("roadmap")&&t.appendChild(this.tabBtn("Roadmap","roadmap")),e.includes("changelog")&&t.appendChild(this.tabBtn("Updates","changelog")),t}tabBtn(t,e){let a=document.createElement("button");return a.className="malto-tab",a.setAttribute("aria-selected",this.state.view===e?"true":"false"),a.textContent=t,a.addEventListener("click",()=>this.go(e)),a}go(t){this.state.view=t,this.state.error=null,this.render(),t==="list"&&this.loadFeedbacks(),t==="roadmap"&&this.loadRoadmap(),t==="changelog"&&this.loadReleases(),t==="detail"&&this.state.selectedFeedback&&this.loadComments(this.state.selectedFeedback.id);}allowedViews(){let t=this.board?.widget.enabledFeatures??["list","submit","vote","comment","roadmap","changelog"];return (this.config.views??["list","submit","roadmap","changelog"]).filter(a=>t.includes(a))}buildView(){let t=document.createElement("div");if(this.state.error){let e=document.createElement("div");e.className="malto-error",e.textContent=this.state.error,t.appendChild(e);}switch(this.state.view){case "list":t.appendChild(this.viewList()),this.state.feedbacks.length===0&&!this.state.loading&&this.loadFeedbacks();break;case "submit":t.appendChild(this.viewSubmit());break;case "auth":t.appendChild(this.viewAuth());break;case "roadmap":t.appendChild(this.viewRoadmap()),Object.keys(this.state.roadmap).length===0&&!this.state.loading&&this.loadRoadmap();break;case "changelog":t.appendChild(this.viewChangelog()),this.state.releases.length===0&&!this.state.loading&&this.loadReleases();break;case "detail":t.appendChild(this.viewDetail());break}return t}viewList(){let t=document.createElement("div");if(this.state.loading)return t.appendChild(this.skeletonList(4)),t;if(this.state.feedbacks.length===0)return t.appendChild(this.emptyState("\u{1F4A1}","No requests yet","Be the first to share an idea or report something.")),t;let e=document.createElement("div");e.className="malto-list";for(let a of this.state.feedbacks)e.appendChild(this.feedbackRow(a));return t.appendChild(e),t}feedbackRow(t){let e=document.createElement("div");e.className="malto-item";let a=document.createElement("button");a.className="malto-vote",a.setAttribute("aria-pressed",t.hasVoted?"true":"false");let o=document.createElement("span");o.className="malto-vote-arrow",o.textContent="\u25B2";let r=document.createElement("span");r.className="malto-vote-count",r.textContent=_(t.votes??0),a.appendChild(o),a.appendChild(r),a.addEventListener("click",m=>{m.stopPropagation(),this.handleVote(t);});let n=document.createElement("div");n.className="malto-item-content";let s=document.createElement("h4");if(s.textContent=t.title,n.appendChild(s),t.description){let m=document.createElement("p");m.textContent=t.description,n.appendChild(m);}let d=document.createElement("div");if(d.className="malto-item-meta",t.status&&t.status!=="BACKLOG"){let m=K(t.status);d.appendChild(m);}let l=document.createElement("span");return l.textContent=z(t.createdAt),d.appendChild(l),n.appendChild(d),e.appendChild(a),e.appendChild(n),e.addEventListener("click",()=>{this.state.selectedFeedback=t,this.go("detail");}),e}viewSubmit(){let t=document.createElement("form");t.className="malto-form";let e=document.createElement("input");e.className="malto-input",e.required=true,e.maxLength=200,e.placeholder="What would you like?";let a=document.createElement("textarea");a.className="malto-textarea",a.maxLength=5e3,a.placeholder="Add some context (optional)";let o=document.createElement("button");return o.className="malto-button",o.textContent="Submit feedback",o.type="submit",t.appendChild(e),t.appendChild(a),t.appendChild(o),t.addEventListener("submit",async r=>{if(r.preventDefault(),!this.state.email){this.go("auth");return}o.setAttribute("disabled","true");try{await this.client.createFeedback({title:e.value.trim(),description:a.value.trim()||void 0}),e.value="",a.value="",await this.loadFeedbacks(),this.go("list");}catch(n){this.state.error=n.message,o.removeAttribute("disabled"),this.render();}}),t}viewAuth(){let t=document.createElement("div");if(this.state.email){let n=document.createElement("p");n.style.fontSize="13px",n.style.color="var(--malto-text)",n.style.marginBottom="10px",n.innerHTML=`Signed in as <strong>${L(this.state.email)}</strong>`;let s=document.createElement("button");return s.className="malto-secondary",s.textContent="Sign out",s.addEventListener("click",()=>{g(this.apiKeyPrefix),this.state.email=null,this.state.name=null,this.go("list");}),t.appendChild(n),t.appendChild(s),t}if(this.state.authStatus==="sent"){let n=document.createElement("p");n.style.fontSize="13px",n.style.color="var(--malto-text)",n.style.marginBottom="12px",n.style.lineHeight="1.5",n.innerHTML=`We sent a sign-in link to <strong>${L(this.state.authEmail)}</strong>. Open the email and paste the token below.`;let s=document.createElement("input");s.className="malto-input",s.placeholder="Paste token from email";let d=document.createElement("button");d.className="malto-button",d.style.marginTop="8px",d.textContent="Verify",d.addEventListener("click",async()=>{d.setAttribute("disabled","true");try{let m=await this.client.verifyMagicLink(s.value.trim());S(this.apiKeyPrefix,{token:m.sessionToken,expiresAt:m.expiresAt,email:m.user.email,name:m.user.name}),this.state.email=m.user.email,this.state.name=m.user.name,this.state.authStatus="idle",this.go("list");}catch(m){this.state.error=m.message,d.removeAttribute("disabled"),this.render();}});let l=document.createElement("button");return l.className="malto-link",l.style.marginTop="12px",l.style.display="block",l.textContent="Use a different email",l.addEventListener("click",()=>{this.state.authStatus="idle",this.render();}),t.appendChild(n),t.appendChild(s),t.appendChild(d),t.appendChild(l),t}let e=document.createElement("form");e.className="malto-form";let a=document.createElement("p");a.style.fontSize="13px",a.style.color="var(--malto-text-muted)",a.style.marginBottom="4px",a.style.lineHeight="1.5",a.textContent="Enter your email to receive a one-click sign-in link.";let o=document.createElement("input");o.className="malto-input",o.type="email",o.required=true,o.placeholder="you@company.com",o.value=this.state.authEmail;let r=document.createElement("button");return r.className="malto-button",r.type="submit",r.textContent="Send sign-in link",e.appendChild(a),e.appendChild(o),e.appendChild(r),e.addEventListener("submit",async n=>{n.preventDefault(),r.setAttribute("disabled","true");try{await this.client.startMagicLink({email:o.value.trim()}),this.state.authEmail=o.value.trim(),this.state.authStatus="sent",this.render();}catch(s){this.state.error=s.message,r.removeAttribute("disabled"),this.render();}}),e}viewRoadmap(){let t=document.createElement("div");if(this.state.loading)return t.appendChild(this.skeletonList(3)),t;let e={PLANNED:"Planned",IN_PROGRESS:"In Progress",COMPLETED:"Done"},a=false;for(let o of ["PLANNED","IN_PROGRESS","COMPLETED"]){let r=this.state.roadmap[o]??[],n=document.createElement("div");n.className="malto-roadmap-col";let s=document.createElement("h5");s.textContent=e[o]??o;let d=document.createElement("span");if(d.className="malto-roadmap-count",d.textContent=String(r.length),s.appendChild(d),n.appendChild(s),r.length===0){let l=document.createElement("div");l.className="malto-empty-desc",l.style.padding="8px 0 12px",l.textContent="Nothing here yet.",n.appendChild(l);}else {a=true;for(let l of r)n.appendChild(this.feedbackRow(l));}t.appendChild(n);}return !a&&Object.keys(this.state.roadmap).length===0&&(t.innerHTML="",t.appendChild(this.emptyState("\u{1F5FA}\uFE0F","Empty roadmap","Once admins move items into Planned, In Progress or Done, you'll see them here."))),t}viewChangelog(){let t=document.createElement("div");if(this.state.loading)return t.appendChild(this.skeletonList(2)),t;if(this.state.releases.length===0)return t.appendChild(this.emptyState("\u2728","No updates yet","Check back soon.")),t;for(let e of this.state.releases){let a=document.createElement("div");if(a.className="malto-release",e.publishedAt){let n=document.createElement("span");n.className="malto-release-date",n.textContent=Y(e.publishedAt),a.appendChild(n);}let o=document.createElement("h4");o.textContent=e.title;let r=document.createElement("p");r.textContent=e.body,a.appendChild(o),a.appendChild(r),t.appendChild(a);}return t}viewDetail(){let t=document.createElement("div"),e=this.state.selectedFeedback;if(!e)return t.appendChild(this.emptyState("\u{1F4ED}","Nothing selected","Pick a request from Feed.")),t;let a=document.createElement("button");if(a.className="malto-back",a.innerHTML='<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> Back',a.addEventListener("click",()=>this.go("list")),t.appendChild(a),t.appendChild(this.feedbackRow(e)),this.allowedViews().includes("comment")){let r=document.createElement("h5");if(r.textContent="Comments",r.style.cssText="margin: 16px 0 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--malto-text-muted); font-weight: 600;",t.appendChild(r),this.state.loading)t.appendChild(this.skeletonList(2));else if(this.state.comments.length===0){let l=document.createElement("div");l.className="malto-empty-desc",l.style.padding="8px 0 12px",l.textContent="No comments yet \u2014 start the conversation.",t.appendChild(l);}else for(let l of this.state.comments){let m=document.createElement("div");m.className="malto-comment";let f=document.createElement("div");f.className="malto-avatar";let M=$(l.author?.avatarUrl);if(M){let u=document.createElement("img");u.src=M,u.alt="",u.referrerPolicy="no-referrer",u.crossOrigin="anonymous",f.appendChild(u);}else f.textContent=(l.author?.name??"?").charAt(0).toUpperCase();let p=document.createElement("div");p.style.flex="1",p.style.minWidth="0";let y=document.createElement("div"),k=document.createElement("span");k.className="malto-comment-author",k.textContent=l.author?.name??"User";let w=document.createElement("span");w.className="malto-comment-time",w.textContent=z(l.createdAt),y.appendChild(k),y.appendChild(w);let C=document.createElement("div");C.className="malto-comment-body",C.textContent=l.body,p.appendChild(y),p.appendChild(C),m.appendChild(f),m.appendChild(p),t.appendChild(m);}let n=document.createElement("form");n.className="malto-form",n.style.marginTop="12px";let s=document.createElement("textarea");s.className="malto-textarea",s.placeholder="Write a comment",s.required=true;let d=document.createElement("button");d.className="malto-button",d.type="submit",d.textContent="Post comment",n.appendChild(s),n.appendChild(d),n.addEventListener("submit",async l=>{if(l.preventDefault(),!this.state.email){this.go("auth");return}d.setAttribute("disabled","true");try{await this.client.addComment(e.id,s.value.trim()),s.value="",await this.loadComments(e.id);}catch(m){this.state.error=m.message;}finally{d.removeAttribute("disabled"),this.render();}}),t.appendChild(n);}return t}skeletonList(t){let e=document.createElement("div");for(let a=0;a<t;a++){let o=document.createElement("div");o.className="malto-skeleton-row";let r=document.createElement("div");r.className="malto-skeleton",r.style.width="44px",r.style.height="48px",r.style.flex="none";let n=document.createElement("div");n.style.flex="1";let s=document.createElement("div");s.className="malto-skeleton",s.style.height="12px",s.style.width="70%",s.style.marginBottom="6px";let d=document.createElement("div");d.className="malto-skeleton",d.style.height="10px",d.style.width="90%",n.appendChild(s),n.appendChild(d),o.appendChild(r),o.appendChild(n),e.appendChild(o);}return e}emptyState(t,e,a){let o=document.createElement("div");o.className="malto-empty";let r=document.createElement("div");r.className="malto-empty-icon",r.style.fontSize="20px",r.textContent=t;let n=document.createElement("div");n.className="malto-empty-title",n.textContent=e;let s=document.createElement("div");return s.className="malto-empty-desc",s.textContent=a,o.appendChild(r),o.appendChild(n),o.appendChild(s),o}async loadFeedbacks(){this.state.loading=true,this.render();try{this.state.feedbacks=await this.client.listFeedbacks();}catch(t){this.state.error=t.message;}finally{this.state.loading=false,this.render();}}async loadRoadmap(){this.state.loading=true,this.render();try{this.state.roadmap=await this.client.roadmap();}catch(t){this.state.error=t.message;}finally{this.state.loading=false,this.render();}}async loadReleases(){this.state.loading=true,this.render();try{this.state.releases=await this.client.releases();}catch(t){this.state.error=t.message;}finally{this.state.loading=false,this.render();}}async loadComments(t){this.state.loading=true,this.render();try{this.state.comments=await this.client.comments(t);}catch(e){this.state.error=e.message;}finally{this.state.loading=false,this.render();}}async handleVote(t){if(!this.state.email){this.go("auth");return}try{let e=await this.client.vote(t.id);t.hasVoted=e.voted,t.votes=e.votes,this.render();}catch(e){this.state.error=e.message,this.render();}}};function K(i){let t=document.createElement("span");t.className=`malto-status malto-status-${i}`;let e=document.createElement("span");e.className="malto-status-dot",t.appendChild(e);let a=document.createElement("span"),o={PLANNED:"Planned",IN_PROGRESS:"In progress",COMPLETED:"Done",DECLINED:"Declined",UNDER_REVIEW:"Under review",BACKLOG:"Backlog"};return a.textContent=o[i]??i,t.appendChild(a),t}function _(i){return i<1e3?String(i):i<1e4?(i/1e3).toFixed(1).replace(/\.0$/,"")+"k":Math.floor(i/1e3)+"k"}function z(i){let t=Date.now()-new Date(i).getTime(),e=Math.floor(t/1e3);if(e<60)return "just now";let a=Math.floor(e/60);if(a<60)return `${a}m`;let o=Math.floor(a/60);if(o<24)return `${o}h`;let r=Math.floor(o/24);if(r<30)return `${r}d`;let n=Math.floor(r/30);return n<12?`${n}mo`:`${Math.floor(n/12)}y`}function Y(i){try{return new Date(i).toLocaleDateString(void 0,{day:"numeric",month:"short",year:"numeric"})}catch{return i}}function L(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function $(i){if(!i||typeof i!="string")return null;let t;try{t=new URL(i,typeof location<"u"?location.href:"https://x");}catch{return null}return t.protocol!=="https:"&&t.protocol!=="http:"?null:t.toString()}var c=null;function ot(i){c&&c.unmount();let t=new v(i);return c=t,t.mount(),t}function nt(){c?.open();}function it(){c?.close();}function st(i){c?.setIdentify(i);}function lt(i){g(i.slice(0,16)),c?.setIdentify(null);}function dt(){c?.unmount(),c=null;}
607
- exports.MaltoApiError=b;exports.MaltoClient=h;exports.MaltoWidget=v;exports.close=it;exports.destroy=dt;exports.identify=st;exports.init=ot;exports.open=nt;exports.reset=lt;return exports;})({});
608
+ `}function D(i){let{r:t,g:e,b:a}=j(i);return {rgb:`${t}, ${e}, ${a}`,contrast:U(t,e,a),tint50:N(t,e,a,.06),tint100:N(t,e,a,.12),tint200:N(t,e,a,.18),shade600:V(t,e,a,-0.18)}}function j(i){let t=i.trim().replace(/^#/,"");return t.length===3&&(t=t.split("").map(e=>e+e).join("")),/^[0-9a-fA-F]{6}$/.test(t)?{r:parseInt(t.slice(0,2),16),g:parseInt(t.slice(2,4),16),b:parseInt(t.slice(4,6),16)}:{r:69,g:47,b:223}}function U(i,t,e){return (.2126*i+.7152*t+.0722*e)/255>.65?"#0f0d23":"#ffffff"}function N(i,t,e,a,r){return `rgba(${i}, ${t}, ${e}, ${a})`}function V(i,t,e,a){let r=n=>Math.max(0,Math.min(255,Math.round(n+255*a))),o=n=>r(n).toString(16).padStart(2,"0");return `#${o(i)}${o(t)}${o(e)}`}var q={"bottom-right":{right:"24px",bottom:"24px"},"bottom-left":{left:"24px",bottom:"24px"},"top-right":{right:"24px",top:"24px"},"top-left":{left:"24px",top:"24px"}},v=class{constructor(t){this.resolvedMode="bubble";this.root=null;this.container=null;this.trigger=null;this.board=null;if(!t.apiKey)throw new Error("Malto: apiKey is required");this.apiKeyPrefix=t.apiKey.slice(0,16),this.config={apiKey:t.apiKey,apiUrl:t.apiUrl??"https://malto-api-production.up.railway.app",mode:t.mode??"auto",position:t.position??"bottom-right",triggerLabel:t.triggerLabel??"Feedback",primaryColor:t.primaryColor,cssVars:t.cssVars,customCss:t.customCss,radius:t.radius??"md",appearance:t.appearance??"auto",zIndex:t.zIndex??2147483600,views:t.views,identify:t.identify,target:t.target,onReady:t.onReady,onError:t.onError};let e=E(this.apiKeyPrefix);this.state={open:false,view:"list",loading:false,error:null,feedbacks:[],roadmap:{},releases:[],selectedFeedback:null,comments:[],authEmail:"",authStatus:"idle",email:e?.email??null,name:e?.name??null},this.client=new h({apiKey:this.config.apiKey,apiUrl:this.config.apiUrl,getSessionToken:()=>E(this.apiKeyPrefix)?.token??null});}async mount(){try{let t=await this.client.board();this.board=t;let e=this.config.primaryColor||t.widget.primaryColor||t.board.boardThemeColor||"#452fdf";z({primary:e,cssVars:this.config.cssVars,customCss:this.config.customCss,radius:this.config.radius,appearance:this.config.appearance}),this.resolvedMode=this.config.mode==="auto"?t.widget.defaultMode:this.config.mode,this.config.identify&&await this.runIdentify(this.config.identify),this.renderHost(this.resolvedMode),this.config.onReady?.();}catch(t){this.config.onError?.(t);}}unmount(){this.root?.parentElement?.removeChild(this.root),this.trigger?.parentElement?.removeChild(this.trigger),this.root=null,this.trigger=null,this.container=null;}open(){this.state.open=true,this.render();}close(){this.state.open=false,this.render();}setIdentify(t){if(!t){g(this.apiKeyPrefix),this.state.email=null,this.state.name=null,this.render();return}this.runIdentify(t);}async runIdentify(t){try{let e=await this.client.identify(t);S(this.apiKeyPrefix,{token:e.sessionToken,expiresAt:e.expiresAt,email:e.user.email,name:e.user.name}),this.state.email=e.user.email,this.state.name=e.user.name,this.render();}catch(e){this.config.onError?.(e);}}renderHost(t){let e=document.createElement("div");if(e.className="malto-root",e.style.setProperty("--malto-z",String(this.config.zIndex)),document.body.appendChild(e),this.root=e,t==="inline"){let a=this.resolveTarget();if(!a){this.config.onError?.(new Error("Malto: inline target not found"));return}let r=document.createElement("div");r.className="malto-root malto-inline",r.style.setProperty("--malto-z",String(this.config.zIndex)),a.appendChild(r),this.container=r,this.state.open=true,this.render();return}if(t==="bubble"){let a=this.buildBubble(),r=q[this.config.position];Object.assign(a.style,r);let o=document.createElement("div");o.className="malto-root",o.style.setProperty("--malto-z",String(this.config.zIndex)),o.appendChild(a),document.body.appendChild(o),this.trigger=o;}else if(t==="trigger"){let a=this.resolveTarget();if(!a){this.config.onError?.(new Error("Malto: trigger target not found"));return}let r=document.createElement("span");r.className="malto-root",r.style.setProperty("--malto-z",String(this.config.zIndex));let o=document.createElement("button");o.className="malto-trigger",o.innerHTML=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg><span>${L(this.config.triggerLabel)}</span>`,o.addEventListener("click",()=>this.open()),r.appendChild(o),a.appendChild(r),this.trigger=r;}else t==="modal"&&(this.state.open=true);this.render();}buildBubble(){let t=document.createElement("button");return t.className="malto-bubble",t.setAttribute("aria-label",this.config.triggerLabel),t.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',t.addEventListener("click",()=>{this.state.open?this.close():this.open();}),t}resolveTarget(){return this.config.target?typeof this.config.target=="string"?document.querySelector(this.config.target):this.config.target:null}render(){if(!this.root)return;if(this.resolvedMode==="inline"){if(!this.container)return;this.container.innerHTML="",this.container.appendChild(this.buildPanelBody());return}if(this.root.innerHTML="",!this.state.open)return;let t=document.createElement("div");t.className="malto-overlay",t.addEventListener("click",a=>{a.target===t&&this.close();});let e=document.createElement("div");e.className="malto-modal",e.appendChild(this.buildPanelBody()),t.appendChild(e),this.root.appendChild(t);}buildPanelBody(){let t=document.createElement("div");t.style.display="flex",t.style.flexDirection="column",t.style.height="100%",t.style.minHeight="0",t.appendChild(this.buildHeader()),t.appendChild(this.buildTabs());let e=document.createElement("div");if(e.className="malto-body",e.appendChild(this.buildView()),t.appendChild(e),this.state.view!=="auth"&&!this.state.email){let a=document.createElement("div");a.className="malto-footer-banner";let r=document.createElement("span");r.innerHTML="Sign in to vote, comment, or submit ideas.";let o=document.createElement("button");o.className="malto-link",o.textContent="Sign in",o.addEventListener("click",()=>this.go("auth")),a.appendChild(r),a.appendChild(o),t.appendChild(a);}return t}buildHeader(){let t=document.createElement("div");t.className="malto-header";let e=document.createElement("div");e.className="malto-header-meta";let a=document.createElement("div");a.className="malto-board-logo";let r=$(this.board?.board.companyLogoUrl);if(r){let n=document.createElement("img");n.src=r,n.alt="",n.referrerPolicy="no-referrer",n.crossOrigin="anonymous",a.appendChild(n);}else a.textContent=(this.board?.board.companyName??this.board?.board.boardName??"M").charAt(0).toUpperCase();let o=document.createElement("h3");if(o.textContent=this.board?.board.boardName??this.board?.board.companyName??"Feedback",e.appendChild(a),e.appendChild(o),t.appendChild(e),this.resolvedMode!=="inline"){let n=document.createElement("button");n.className="malto-close",n.setAttribute("aria-label","Close"),n.innerHTML='<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',n.addEventListener("click",()=>this.close()),t.appendChild(n);}return t}buildTabs(){let t=document.createElement("div");t.className="malto-tabs";let e=this.allowedViews();return e.includes("list")&&t.appendChild(this.tabBtn("Feed","list")),e.includes("submit")&&t.appendChild(this.tabBtn("New","submit")),e.includes("roadmap")&&t.appendChild(this.tabBtn("Roadmap","roadmap")),e.includes("changelog")&&t.appendChild(this.tabBtn("Updates","changelog")),t}tabBtn(t,e){let a=document.createElement("button");return a.className="malto-tab",a.setAttribute("aria-selected",this.state.view===e?"true":"false"),a.textContent=t,a.addEventListener("click",()=>this.go(e)),a}go(t){this.state.view=t,this.state.error=null,this.render(),t==="list"&&this.loadFeedbacks(),t==="roadmap"&&this.loadRoadmap(),t==="changelog"&&this.loadReleases(),t==="detail"&&this.state.selectedFeedback&&this.loadComments(this.state.selectedFeedback.id);}allowedViews(){let t=this.board?.widget.enabledFeatures??["list","submit","vote","comment","roadmap","changelog"];return (this.config.views??["list","submit","roadmap","changelog"]).filter(a=>t.includes(a))}buildView(){let t=document.createElement("div");if(this.state.error){let e=document.createElement("div");e.className="malto-error",e.textContent=this.state.error,t.appendChild(e);}switch(this.state.view){case "list":t.appendChild(this.viewList()),this.state.feedbacks.length===0&&!this.state.loading&&this.loadFeedbacks();break;case "submit":t.appendChild(this.viewSubmit());break;case "auth":t.appendChild(this.viewAuth());break;case "roadmap":t.appendChild(this.viewRoadmap()),Object.keys(this.state.roadmap).length===0&&!this.state.loading&&this.loadRoadmap();break;case "changelog":t.appendChild(this.viewChangelog()),this.state.releases.length===0&&!this.state.loading&&this.loadReleases();break;case "detail":t.appendChild(this.viewDetail());break}return t}viewList(){let t=document.createElement("div");if(this.state.loading)return t.appendChild(this.skeletonList(4)),t;if(this.state.feedbacks.length===0)return t.appendChild(this.emptyState("\u{1F4A1}","No requests yet","Be the first to share an idea or report something.")),t;let e=document.createElement("div");e.className="malto-list";for(let a of this.state.feedbacks)e.appendChild(this.feedbackRow(a));return t.appendChild(e),t}feedbackRow(t){let e=document.createElement("div");e.className="malto-item";let a=document.createElement("button");a.className="malto-vote",a.setAttribute("aria-pressed",t.hasVoted?"true":"false");let r=document.createElement("span");r.className="malto-vote-arrow",r.textContent="\u25B2";let o=document.createElement("span");o.className="malto-vote-count",o.textContent=_(t.votes??0),a.appendChild(r),a.appendChild(o),a.addEventListener("click",m=>{m.stopPropagation(),this.handleVote(t);});let n=document.createElement("div");n.className="malto-item-content";let s=document.createElement("h4");if(s.textContent=t.title,n.appendChild(s),t.description){let m=document.createElement("p");m.textContent=t.description,n.appendChild(m);}let d=document.createElement("div");if(d.className="malto-item-meta",t.status&&t.status!=="BACKLOG"){let m=K(t.status);d.appendChild(m);}let l=document.createElement("span");return l.textContent=R(t.createdAt),d.appendChild(l),n.appendChild(d),e.appendChild(a),e.appendChild(n),e.addEventListener("click",()=>{this.state.selectedFeedback=t,this.go("detail");}),e}viewSubmit(){let t=document.createElement("form");t.className="malto-form";let e=document.createElement("input");e.className="malto-input",e.required=true,e.maxLength=200,e.placeholder="What would you like?";let a=document.createElement("textarea");a.className="malto-textarea",a.maxLength=5e3,a.placeholder="Add some context (optional)";let r=document.createElement("button");return r.className="malto-button",r.textContent="Submit feedback",r.type="submit",t.appendChild(e),t.appendChild(a),t.appendChild(r),t.addEventListener("submit",async o=>{if(o.preventDefault(),!this.state.email){this.go("auth");return}r.setAttribute("disabled","true");try{await this.client.createFeedback({title:e.value.trim(),description:a.value.trim()||void 0}),e.value="",a.value="",await this.loadFeedbacks(),this.go("list");}catch(n){this.state.error=n.message,r.removeAttribute("disabled"),this.render();}}),t}viewAuth(){let t=document.createElement("div");if(this.state.email){let n=document.createElement("p");n.style.fontSize="13px",n.style.color="var(--malto-text)",n.style.marginBottom="10px",n.innerHTML=`Signed in as <strong>${L(this.state.email)}</strong>`;let s=document.createElement("button");return s.className="malto-secondary",s.textContent="Sign out",s.addEventListener("click",()=>{g(this.apiKeyPrefix),this.state.email=null,this.state.name=null,this.go("list");}),t.appendChild(n),t.appendChild(s),t}if(this.state.authStatus==="sent"){let n=document.createElement("p");n.style.fontSize="13px",n.style.color="var(--malto-text)",n.style.marginBottom="12px",n.style.lineHeight="1.5",n.innerHTML=`We sent a sign-in link to <strong>${L(this.state.authEmail)}</strong>. Open the email and paste the token below.`;let s=document.createElement("input");s.className="malto-input",s.placeholder="Paste token from email";let d=document.createElement("button");d.className="malto-button",d.style.marginTop="8px",d.textContent="Verify",d.addEventListener("click",async()=>{d.setAttribute("disabled","true");try{let m=await this.client.verifyMagicLink(s.value.trim());S(this.apiKeyPrefix,{token:m.sessionToken,expiresAt:m.expiresAt,email:m.user.email,name:m.user.name}),this.state.email=m.user.email,this.state.name=m.user.name,this.state.authStatus="idle",this.go("list");}catch(m){this.state.error=m.message,d.removeAttribute("disabled"),this.render();}});let l=document.createElement("button");return l.className="malto-link",l.style.marginTop="12px",l.style.display="block",l.textContent="Use a different email",l.addEventListener("click",()=>{this.state.authStatus="idle",this.render();}),t.appendChild(n),t.appendChild(s),t.appendChild(d),t.appendChild(l),t}let e=document.createElement("form");e.className="malto-form";let a=document.createElement("p");a.style.fontSize="13px",a.style.color="var(--malto-text-muted)",a.style.marginBottom="4px",a.style.lineHeight="1.5",a.textContent="Enter your email to receive a one-click sign-in link.";let r=document.createElement("input");r.className="malto-input",r.type="email",r.required=true,r.placeholder="you@company.com",r.value=this.state.authEmail;let o=document.createElement("button");return o.className="malto-button",o.type="submit",o.textContent="Send sign-in link",e.appendChild(a),e.appendChild(r),e.appendChild(o),e.addEventListener("submit",async n=>{n.preventDefault(),o.setAttribute("disabled","true");try{await this.client.startMagicLink({email:r.value.trim()}),this.state.authEmail=r.value.trim(),this.state.authStatus="sent",this.render();}catch(s){this.state.error=s.message,o.removeAttribute("disabled"),this.render();}}),e}viewRoadmap(){let t=document.createElement("div");if(this.state.loading)return t.appendChild(this.skeletonList(3)),t;let e={PLANNED:"Planned",IN_PROGRESS:"In Progress",COMPLETED:"Done"},a=false;for(let r of ["PLANNED","IN_PROGRESS","COMPLETED"]){let o=this.state.roadmap[r]??[],n=document.createElement("div");n.className="malto-roadmap-col";let s=document.createElement("h5");s.textContent=e[r]??r;let d=document.createElement("span");if(d.className="malto-roadmap-count",d.textContent=String(o.length),s.appendChild(d),n.appendChild(s),o.length===0){let l=document.createElement("div");l.className="malto-empty-desc",l.style.padding="8px 0 12px",l.textContent="Nothing here yet.",n.appendChild(l);}else {a=true;for(let l of o)n.appendChild(this.feedbackRow(l));}t.appendChild(n);}return !a&&Object.keys(this.state.roadmap).length===0&&(t.innerHTML="",t.appendChild(this.emptyState("\u{1F5FA}\uFE0F","Empty roadmap","Once admins move items into Planned, In Progress or Done, you'll see them here."))),t}viewChangelog(){let t=document.createElement("div");if(this.state.loading)return t.appendChild(this.skeletonList(2)),t;if(this.state.releases.length===0)return t.appendChild(this.emptyState("\u2728","No updates yet","Check back soon.")),t;for(let e of this.state.releases){let a=document.createElement("div");if(a.className="malto-release",e.publishedAt){let n=document.createElement("span");n.className="malto-release-date",n.textContent=Y(e.publishedAt),a.appendChild(n);}let r=document.createElement("h4");r.textContent=e.title;let o=document.createElement("p");o.textContent=e.body,a.appendChild(r),a.appendChild(o),t.appendChild(a);}return t}viewDetail(){let t=document.createElement("div"),e=this.state.selectedFeedback;if(!e)return t.appendChild(this.emptyState("\u{1F4ED}","Nothing selected","Pick a request from Feed.")),t;let a=document.createElement("button");if(a.className="malto-back",a.innerHTML='<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> Back',a.addEventListener("click",()=>this.go("list")),t.appendChild(a),t.appendChild(this.feedbackRow(e)),this.allowedViews().includes("comment")){let o=document.createElement("h5");if(o.textContent="Comments",o.style.cssText="margin: 16px 0 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--malto-text-muted); font-weight: 600;",t.appendChild(o),this.state.loading)t.appendChild(this.skeletonList(2));else if(this.state.comments.length===0){let l=document.createElement("div");l.className="malto-empty-desc",l.style.padding="8px 0 12px",l.textContent="No comments yet \u2014 start the conversation.",t.appendChild(l);}else for(let l of this.state.comments){let m=document.createElement("div");m.className="malto-comment";let f=document.createElement("div");f.className="malto-avatar";let M=$(l.author?.avatarUrl);if(M){let u=document.createElement("img");u.src=M,u.alt="",u.referrerPolicy="no-referrer",u.crossOrigin="anonymous",f.appendChild(u);}else f.textContent=(l.author?.name??"?").charAt(0).toUpperCase();let p=document.createElement("div");p.style.flex="1",p.style.minWidth="0";let y=document.createElement("div"),k=document.createElement("span");k.className="malto-comment-author",k.textContent=l.author?.name??"User";let w=document.createElement("span");w.className="malto-comment-time",w.textContent=R(l.createdAt),y.appendChild(k),y.appendChild(w);let C=document.createElement("div");C.className="malto-comment-body",C.textContent=l.body,p.appendChild(y),p.appendChild(C),m.appendChild(f),m.appendChild(p),t.appendChild(m);}let n=document.createElement("form");n.className="malto-form",n.style.marginTop="12px";let s=document.createElement("textarea");s.className="malto-textarea",s.placeholder="Write a comment",s.required=true;let d=document.createElement("button");d.className="malto-button",d.type="submit",d.textContent="Post comment",n.appendChild(s),n.appendChild(d),n.addEventListener("submit",async l=>{if(l.preventDefault(),!this.state.email){this.go("auth");return}d.setAttribute("disabled","true");try{await this.client.addComment(e.id,s.value.trim()),s.value="",await this.loadComments(e.id);}catch(m){this.state.error=m.message;}finally{d.removeAttribute("disabled"),this.render();}}),t.appendChild(n);}return t}skeletonList(t){let e=document.createElement("div");for(let a=0;a<t;a++){let r=document.createElement("div");r.className="malto-skeleton-row";let o=document.createElement("div");o.className="malto-skeleton",o.style.width="44px",o.style.height="48px",o.style.flex="none";let n=document.createElement("div");n.style.flex="1";let s=document.createElement("div");s.className="malto-skeleton",s.style.height="12px",s.style.width="70%",s.style.marginBottom="6px";let d=document.createElement("div");d.className="malto-skeleton",d.style.height="10px",d.style.width="90%",n.appendChild(s),n.appendChild(d),r.appendChild(o),r.appendChild(n),e.appendChild(r);}return e}emptyState(t,e,a){let r=document.createElement("div");r.className="malto-empty";let o=document.createElement("div");o.className="malto-empty-icon",o.style.fontSize="20px",o.textContent=t;let n=document.createElement("div");n.className="malto-empty-title",n.textContent=e;let s=document.createElement("div");return s.className="malto-empty-desc",s.textContent=a,r.appendChild(o),r.appendChild(n),r.appendChild(s),r}async loadFeedbacks(){this.state.loading=true,this.render();try{this.state.feedbacks=await this.client.listFeedbacks();}catch(t){this.state.error=t.message;}finally{this.state.loading=false,this.render();}}async loadRoadmap(){this.state.loading=true,this.render();try{this.state.roadmap=await this.client.roadmap();}catch(t){this.state.error=t.message;}finally{this.state.loading=false,this.render();}}async loadReleases(){this.state.loading=true,this.render();try{this.state.releases=await this.client.releases();}catch(t){this.state.error=t.message;}finally{this.state.loading=false,this.render();}}async loadComments(t){this.state.loading=true,this.render();try{this.state.comments=await this.client.comments(t);}catch(e){this.state.error=e.message;}finally{this.state.loading=false,this.render();}}async handleVote(t){if(!this.state.email){this.go("auth");return}try{let e=await this.client.vote(t.id);t.hasVoted=e.voted,t.votes=e.votes,this.render();}catch(e){this.state.error=e.message,this.render();}}};function K(i){let t=document.createElement("span");t.className=`malto-status malto-status-${i}`;let e=document.createElement("span");e.className="malto-status-dot",t.appendChild(e);let a=document.createElement("span"),r={PLANNED:"Planned",IN_PROGRESS:"In progress",COMPLETED:"Done",DECLINED:"Declined",UNDER_REVIEW:"Under review",BACKLOG:"Backlog"};return a.textContent=r[i]??i,t.appendChild(a),t}function _(i){return i<1e3?String(i):i<1e4?(i/1e3).toFixed(1).replace(/\.0$/,"")+"k":Math.floor(i/1e3)+"k"}function R(i){let t=Date.now()-new Date(i).getTime(),e=Math.floor(t/1e3);if(e<60)return "just now";let a=Math.floor(e/60);if(a<60)return `${a}m`;let r=Math.floor(a/60);if(r<24)return `${r}h`;let o=Math.floor(r/24);if(o<30)return `${o}d`;let n=Math.floor(o/30);return n<12?`${n}mo`:`${Math.floor(n/12)}y`}function Y(i){try{return new Date(i).toLocaleDateString(void 0,{day:"numeric",month:"short",year:"numeric"})}catch{return i}}function L(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function $(i){if(!i||typeof i!="string")return null;let t;try{t=new URL(i,typeof location<"u"?location.href:"https://x");}catch{return null}return t.protocol!=="https:"&&t.protocol!=="http:"?null:t.toString()}var c=null;function rt(i){c&&c.unmount();let t=new v(i);return c=t,t.mount(),t}function nt(){c?.open();}function it(){c?.close();}function st(i){c?.setIdentify(i);}function lt(i){g(i.slice(0,16)),c?.setIdentify(null);}function dt(){c?.unmount(),c=null;}
609
+ exports.MaltoApiError=b;exports.MaltoClient=h;exports.MaltoWidget=v;exports.close=it;exports.destroy=dt;exports.identify=st;exports.init=rt;exports.open=nt;exports.reset=lt;return exports;})({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malto/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Embeddable feedback widget for Malto.io — vanilla JavaScript SDK with zero runtime dependencies.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/malto-io/malto-sdk",