@helpway/react 0.8.3 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helpway/react",
3
- "version": "0.8.3",
3
+ "version": "0.10.0",
4
4
  "description": "Official React SDK for Helpway — drop-in AI chat support widget with headless hooks for custom UIs.",
5
5
  "keywords": [
6
6
  "helpway",
@@ -51,8 +51,6 @@
51
51
  "zustand": "^5.0.11"
52
52
  },
53
53
  "devDependencies": {
54
- "@helpway/types": "workspace:*",
55
- "@helpway/widget-core": "workspace:*",
56
54
  "@types/react": "^19.1.6",
57
55
  "@types/react-dom": "^19.1.6",
58
56
  "@central-icons-react/round-outlined-radius-2-stroke-2": "^1.1.213",
@@ -354,10 +354,11 @@
354
354
  /* Reading mode — applied when the visitor enters a content detail view
355
355
  (help article, changelog entry). Wider + taller for comfortable long-form
356
356
  reading. Mobile (<480px) ignores this — the @media block forces 100% +
357
- beats this rule by source order. */
357
+ beats this rule by source order. Bottom offset (72px bubble + 20px gap)
358
+ is subtracted so the window never clips above the viewport. */
358
359
  .hw-window--reading {
359
360
  width: min(720px, calc(100vw - 40px));
360
- height: min(800px, calc(100vh - 100px));
361
+ height: min(800px, calc(100vh - 112px));
361
362
  }
362
363
 
363
364
  @keyframes hw-window-open {
@@ -476,12 +477,17 @@
476
477
  align-items: center;
477
478
  justify-content: center;
478
479
  border-radius: 10px;
479
- overflow: hidden;
480
480
  }
481
481
  .hw-hero-bot-icon svg {
482
482
  width: 32px;
483
483
  height: 32px;
484
484
  }
485
+ .hw-hero-bot-icon .hw-agent-img,
486
+ .hw-hero-bot-icon .hw-agent-icon {
487
+ border-radius: inherit;
488
+ overflow: hidden;
489
+ object-fit: contain;
490
+ }
485
491
 
486
492
  .hw-hero-greeting {
487
493
  font-size: 26px;
@@ -583,7 +589,6 @@
583
589
  align-items: center;
584
590
  justify-content: center;
585
591
  border-radius: 8px;
586
- overflow: hidden;
587
592
  /* Two-tier fallback so site overrides still win cleanly:
588
593
  1. Site stylesheet → `--hw-agent-bg` (highest priority)
589
594
  2. Widget smart default → `--hw-agent-bg-default` (set when the
@@ -605,6 +610,12 @@
605
610
  width: 100%;
606
611
  height: 100%;
607
612
  object-fit: cover;
613
+ border-radius: inherit;
614
+ }
615
+ .hw-header-bot-icon .hw-agent-img,
616
+ .hw-header-bot-icon .hw-agent-icon {
617
+ border-radius: inherit;
618
+ overflow: hidden;
608
619
  }
609
620
  .hw-header-bot-icon .hw-agent-img {
610
621
  object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));
@@ -1156,6 +1167,7 @@
1156
1167
  .hw-tabs-item svg {
1157
1168
  width: 22px;
1158
1169
  height: 22px;
1170
+ overflow: visible;
1159
1171
  }
1160
1172
  .hw-tabs-item--active {
1161
1173
  color: var(--hw-text);
@@ -1535,6 +1547,85 @@
1535
1547
  }
1536
1548
  }
1537
1549
 
1550
+ /* ── Streaming cursor ────────────────────── */
1551
+
1552
+ .hw-streaming-cursor {
1553
+ display: inline-block;
1554
+ width: 2px;
1555
+ height: 1em;
1556
+ background: currentColor;
1557
+ opacity: 0.6;
1558
+ margin-left: 1px;
1559
+ vertical-align: text-bottom;
1560
+ animation: hw-cursor-blink 0.8s step-end infinite;
1561
+ }
1562
+
1563
+ @keyframes hw-cursor-blink {
1564
+ 50% { opacity: 0; }
1565
+ }
1566
+
1567
+ /* ── Link preview card ───────────────────── */
1568
+
1569
+ .hw-link-preview {
1570
+ display: flex;
1571
+ flex-direction: column;
1572
+ border: 1px solid rgba(0, 0, 0, 0.08);
1573
+ border-radius: 10px;
1574
+ overflow: hidden;
1575
+ text-decoration: none;
1576
+ color: inherit;
1577
+ margin-top: 6px;
1578
+ transition: background 0.15s;
1579
+ }
1580
+
1581
+ .hw-link-preview:hover {
1582
+ background: rgba(0, 0, 0, 0.02);
1583
+ }
1584
+
1585
+ .hw-link-preview-img {
1586
+ width: 100%;
1587
+ max-height: 140px;
1588
+ object-fit: cover;
1589
+ }
1590
+
1591
+ .hw-link-preview-body {
1592
+ padding: 10px 12px;
1593
+ display: flex;
1594
+ flex-direction: column;
1595
+ gap: 3px;
1596
+ }
1597
+
1598
+ .hw-link-preview-favicon {
1599
+ width: 16px;
1600
+ height: 16px;
1601
+ border-radius: 2px;
1602
+ }
1603
+
1604
+ .hw-link-preview-title {
1605
+ font-size: 13px;
1606
+ font-weight: 600;
1607
+ line-height: 1.3;
1608
+ color: var(--hw-text, #1a1a1a);
1609
+ }
1610
+
1611
+ .hw-link-preview-desc {
1612
+ font-size: 12px;
1613
+ line-height: 1.4;
1614
+ color: var(--hw-text-muted, #6b7280);
1615
+ }
1616
+
1617
+ .hw-link-preview-url {
1618
+ font-size: 11px;
1619
+ color: var(--hw-text-muted, #9ca3af);
1620
+ }
1621
+
1622
+ .hw-msg-links {
1623
+ display: flex;
1624
+ flex-direction: column;
1625
+ gap: 6px;
1626
+ max-width: 280px;
1627
+ }
1628
+
1538
1629
  /* ════════════════════════════════════════════════
1539
1630
  LOADING STATE
1540
1631
  ════════════════════════════════════════════════ */
@@ -1891,7 +1982,10 @@
1891
1982
  }
1892
1983
 
1893
1984
  .hw-composer-input {
1894
- flex: 1;
1985
+ /* No `flex: 1` — column flex with `flex-basis: 0%` makes the browser
1986
+ ignore both `style.height` (JS resize) AND `field-sizing: content`,
1987
+ clamping the textarea to `min-height` after 2 lines. Cross-axis
1988
+ stretch still gives full width via the parent's `align-items` default. */
1895
1989
  resize: none;
1896
1990
  border: none;
1897
1991
  padding: 12px 16px 4px;
@@ -2593,6 +2687,38 @@
2593
2687
  transition: transform 0.15s, box-shadow 0.15s;
2594
2688
  }
2595
2689
 
2690
+ /* Anchored placement — used when the preview is rendered next to a
2691
+ custom trigger (e.g. a sidebar item) instead of the floating
2692
+ launcher. Drops the launcher-bound absolute pin AND the fixed 300px
2693
+ so the consumer's own positioned + sized wrapper fully controls it
2694
+ (e.g. fit within a narrow sidebar instead of overflowing into page
2695
+ content). Shadow, radius, animation, hover stay identical. Double-
2696
+ class so it always beats the single-class `.hw-preview` regardless
2697
+ of source order. */
2698
+ .hw-preview.hw-preview--anchored {
2699
+ position: static;
2700
+ bottom: auto;
2701
+ right: auto;
2702
+ width: 100%;
2703
+ max-width: 100%;
2704
+ }
2705
+
2706
+ /* Anchored avatar — dekorasyonsuz: the launcher's gradient puck makes
2707
+ sense above a floating bubble, but in a sidebar it competes with
2708
+ surrounding chrome. Consumers want the bare agent mark and apply
2709
+ their own framing (e.g. dark-mode inversion). SDK only drops the
2710
+ gradient bg here; size and radius inherit from the base. The
2711
+ img/svg sizing stays so an uploaded logo doesn't get cropped. */
2712
+ .hw-preview.hw-preview--anchored .hw-preview-avatar {
2713
+ background: none;
2714
+ }
2715
+ .hw-preview.hw-preview--anchored .hw-preview-avatar img,
2716
+ .hw-preview.hw-preview--anchored .hw-preview-avatar svg {
2717
+ width: 100%;
2718
+ height: 100%;
2719
+ object-fit: contain;
2720
+ }
2721
+
2596
2722
  .hw-preview:hover {
2597
2723
  transform: translateY(-2px);
2598
2724
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.08);
@@ -2693,6 +2819,20 @@
2693
2819
  padding-bottom: 14px;
2694
2820
  }
2695
2821
 
2822
+ /* Optional source caption (e.g. "via Helpway"). Thin separated footer
2823
+ so it reads as provenance metadata, not message content. Only
2824
+ rendered when the consumer passes a `footer` — launcher omits it,
2825
+ keeping the original visual byte-identical. */
2826
+ .hw-preview-footer {
2827
+ margin-top: 2px;
2828
+ padding: 8px 14px 12px;
2829
+ border-top: 1px solid var(--hw-border);
2830
+ font-size: 11px;
2831
+ line-height: 1.3;
2832
+ color: var(--hw-text-2);
2833
+ opacity: 0.65;
2834
+ }
2835
+
2696
2836
  .hw-preview-prompt {
2697
2837
  padding: 2px 14px 6px;
2698
2838
  font-size: 14px;
@@ -2727,6 +2867,187 @@
2727
2867
  border-color: var(--hw-brand, #000);
2728
2868
  }
2729
2869
 
2870
+ /* ── Preview closing animation ──────────────────────────── */
2871
+ .hw-preview--closing {
2872
+ animation: hw-preview-out 0.2s ease-in forwards;
2873
+ }
2874
+
2875
+ /* ── Announcement preview stack (multiple tabs) ──────── */
2876
+ .hw-preview-stack {
2877
+ position: absolute;
2878
+ bottom: calc(100% + 12px);
2879
+ right: 0;
2880
+ display: flex;
2881
+ flex-direction: column;
2882
+ gap: 8px;
2883
+ }
2884
+
2885
+ .hw-preview-stack .hw-preview {
2886
+ position: relative;
2887
+ bottom: auto;
2888
+ right: auto;
2889
+ }
2890
+
2891
+ /* ── Announcement preview modifier ─────────────────────── */
2892
+ .hw-preview--announcement {
2893
+ width: 340px;
2894
+ }
2895
+
2896
+ .hw-preview--announcement .hw-preview-body--title {
2897
+ font-weight: 600;
2898
+ color: var(--hw-text);
2899
+ font-size: 15px;
2900
+ line-height: 1.3;
2901
+ padding-top: 10px;
2902
+ }
2903
+
2904
+ .hw-preview--announcement .hw-preview-body--desc {
2905
+ font-size: 13px;
2906
+ color: var(--hw-text-2);
2907
+ line-height: 1.5;
2908
+ padding-bottom: 16px;
2909
+ }
2910
+
2911
+ .hw-announcement-badge {
2912
+ display: inline-block;
2913
+ margin: 8px 14px 0;
2914
+ padding: 2px 8px;
2915
+ font-size: 10px;
2916
+ font-weight: 700;
2917
+ text-transform: uppercase;
2918
+ letter-spacing: 0.04em;
2919
+ color: var(--hw-primary);
2920
+ background: color-mix(in srgb, var(--hw-primary) 10%, transparent);
2921
+ border-radius: 4px;
2922
+ }
2923
+
2924
+ /* ── What's New card (Home tab) ────────────────────────── */
2925
+ .hw-whats-new {
2926
+ border-radius: 14px;
2927
+ background: var(--hw-bg);
2928
+ border: 1px solid rgba(0, 0, 0, 0.06);
2929
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);
2930
+ overflow: hidden;
2931
+ }
2932
+
2933
+ .hw-whats-new-header {
2934
+ display: flex;
2935
+ align-items: center;
2936
+ justify-content: space-between;
2937
+ padding: 12px 14px 0;
2938
+ }
2939
+
2940
+ .hw-whats-new-title {
2941
+ font-size: 12px;
2942
+ font-weight: 600;
2943
+ color: var(--hw-text-2);
2944
+ }
2945
+
2946
+ .hw-whats-new-view-all {
2947
+ font-size: 11px;
2948
+ font-weight: 500;
2949
+ color: var(--hw-primary);
2950
+ background: none;
2951
+ border: none;
2952
+ cursor: pointer;
2953
+ padding: 0;
2954
+ font-family: inherit;
2955
+ }
2956
+ .hw-whats-new-view-all:hover {
2957
+ opacity: 0.8;
2958
+ }
2959
+
2960
+ .hw-whats-new-list {
2961
+ display: flex;
2962
+ flex-direction: column;
2963
+ }
2964
+
2965
+ .hw-whats-new-item {
2966
+ display: flex;
2967
+ flex-direction: column;
2968
+ gap: 2px;
2969
+ width: 100%;
2970
+ padding: 10px 14px;
2971
+ border: none;
2972
+ border-bottom: 1px solid var(--hw-border);
2973
+ background: none;
2974
+ cursor: pointer;
2975
+ text-align: left;
2976
+ font-family: inherit;
2977
+ color: var(--hw-text);
2978
+ transition: background-color 140ms ease;
2979
+ }
2980
+ .hw-whats-new-item:last-child {
2981
+ border-bottom: none;
2982
+ }
2983
+ .hw-whats-new-item:hover {
2984
+ background: rgba(0, 0, 0, 0.03);
2985
+ }
2986
+
2987
+ .hw-whats-new-item-top {
2988
+ display: flex;
2989
+ align-items: center;
2990
+ gap: 8px;
2991
+ }
2992
+
2993
+ .hw-whats-new-badge {
2994
+ font-size: 10px;
2995
+ font-weight: 700;
2996
+ text-transform: uppercase;
2997
+ letter-spacing: 0.04em;
2998
+ color: var(--hw-primary);
2999
+ }
3000
+
3001
+ .hw-whats-new-time {
3002
+ font-size: 11px;
3003
+ color: var(--hw-text-3);
3004
+ margin-left: auto;
3005
+ }
3006
+
3007
+ .hw-whats-new-item-title {
3008
+ font-size: 13px;
3009
+ font-weight: 600;
3010
+ color: var(--hw-text);
3011
+ line-height: 1.3;
3012
+ display: flex;
3013
+ align-items: baseline;
3014
+ gap: 8px;
3015
+ }
3016
+
3017
+ .hw-whats-new-time-inline {
3018
+ font-size: 11px;
3019
+ font-weight: 400;
3020
+ color: var(--hw-text-3);
3021
+ margin-left: auto;
3022
+ flex-shrink: 0;
3023
+ }
3024
+
3025
+ .hw-whats-new-item-body {
3026
+ font-size: 12px;
3027
+ color: var(--hw-text-2);
3028
+ line-height: 1.4;
3029
+ }
3030
+
3031
+ /* ── Announcement dot (tabs + launcher) ────────────────── */
3032
+ .hw-tabs-dot {
3033
+ position: absolute;
3034
+ top: -2px;
3035
+ right: -6px;
3036
+ width: 8px;
3037
+ height: 8px;
3038
+ border-radius: 50%;
3039
+ background: var(--hw-primary);
3040
+ animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
3041
+ }
3042
+
3043
+ .hw-bubble-badge-dot {
3044
+ display: block;
3045
+ width: 8px;
3046
+ height: 8px;
3047
+ border-radius: 50%;
3048
+ background: white;
3049
+ }
3050
+
2730
3051
  /* ═══════════════════════════════════════════════════════════
2731
3052
  Content Tabs — Better i18n Content CMS integration
2732
3053
  Generic list → detail pattern for all content types
@@ -2887,7 +3208,8 @@
2887
3208
  padding: 16px;
2888
3209
  overflow-y: auto;
2889
3210
  overscroll-behavior: contain;
2890
- height: 100%;
3211
+ flex: 1;
3212
+ min-height: 0;
2891
3213
  }
2892
3214
 
2893
3215
  .hw-content-detail-header {