@helpway/react 0.15.3 → 0.17.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.15.3",
3
+ "version": "0.17.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",
@@ -40,6 +40,7 @@
40
40
  "scripts": {
41
41
  "build": "tsup",
42
42
  "typecheck": "tsc --noEmit",
43
+ "test": "bun test",
43
44
  "sync:icons": "bun scripts/sync-icons.ts",
44
45
  "prepublishOnly": "bun run build",
45
46
  "prepack": "bun run build && bun scripts/apply-publish-config.ts",
@@ -51,9 +52,10 @@
51
52
  "zustand": "^5.0.11"
52
53
  },
53
54
  "devDependencies": {
55
+ "@central-icons-react/round-outlined-radius-2-stroke-2": "^1.1.213",
56
+ "@happy-dom/global-registrator": "^20.14.0",
54
57
  "@types/react": "^19.1.6",
55
58
  "@types/react-dom": "^19.1.6",
56
- "@central-icons-react/round-outlined-radius-2-stroke-2": "^1.1.213",
57
59
  "react-dom": "^19.1.6",
58
60
  "tsup": "^8.3.5",
59
61
  "typescript": "~5.9.3"
@@ -98,6 +98,15 @@
98
98
  border-radius: inherit;
99
99
  }
100
100
 
101
+ /* A host `agentAvatar` brings its own shape and colour: every box that holds
102
+ one drops its tile radius and fill so the host's mark is not framed by a
103
+ rounded square it did not ask for. */
104
+ .hw-widget :is(.hw-header-bot-icon, .hw-hero-bot-icon, .hw-conv-card-avatar, .hw-event-avatar, .hw-bubble-icon--bot):has(> .hw-agent-custom) {
105
+ border-radius: 50%;
106
+ background: transparent;
107
+ padding: 0;
108
+ }
109
+
101
110
  /* ── Focus Styles ──────────────────────────────── */
102
111
  .hw-widget :focus-visible {
103
112
  outline: 2px solid var(--hw-primary);
@@ -219,7 +228,7 @@
219
228
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;
220
229
  }
221
230
 
222
- .hw-bubble-icon svg {
231
+ .hw-bubble-icon svg:not(.hw-agent-custom svg) {
223
232
  width: 22px;
224
233
  height: 22px;
225
234
  }
@@ -478,7 +487,10 @@
478
487
  justify-content: center;
479
488
  border-radius: 10px;
480
489
  }
481
- .hw-hero-bot-icon svg {
490
+ /* Direct children only (the Helpway mark, a preset icon): a host `agentAvatar`
491
+ brings its own SVG and sizing, which this must not resize. */
492
+ .hw-hero-bot-icon > svg,
493
+ .hw-hero-bot-icon > .hw-agent-icon > svg {
482
494
  width: 32px;
483
495
  height: 32px;
484
496
  }
@@ -599,7 +611,8 @@
599
611
  chain — exactly the cascade behavior we want. */
600
612
  background: var(--hw-agent-bg, var(--hw-agent-bg-default, transparent));
601
613
  }
602
- .hw-header-bot-icon svg {
614
+ .hw-header-bot-icon > svg,
615
+ .hw-header-bot-icon > .hw-agent-icon > svg {
603
616
  width: 24px;
604
617
  height: 24px;
605
618
  }
@@ -893,7 +906,7 @@
893
906
  height: 32px;
894
907
  border-radius: 8px;
895
908
  }
896
- .hw-recent-row .hw-conv-card-avatar svg {
909
+ .hw-recent-row .hw-conv-card-avatar svg:not(.hw-agent-custom svg) {
897
910
  width: 18px;
898
911
  height: 18px;
899
912
  }
@@ -995,7 +1008,7 @@
995
1008
  flex-shrink: 0;
996
1009
  overflow: hidden;
997
1010
  }
998
- .hw-conv-card-avatar svg {
1011
+ .hw-conv-card-avatar svg:not(.hw-agent-custom svg) {
999
1012
  width: 20px;
1000
1013
  height: 20px;
1001
1014
  }
@@ -2755,7 +2768,7 @@
2755
2768
  background: none;
2756
2769
  }
2757
2770
  .hw-preview.hw-preview--anchored .hw-preview-avatar img,
2758
- .hw-preview.hw-preview--anchored .hw-preview-avatar svg {
2771
+ .hw-preview.hw-preview--anchored .hw-preview-avatar svg:not(.hw-agent-custom svg) {
2759
2772
  width: 100%;
2760
2773
  height: 100%;
2761
2774
  object-fit: contain;
@@ -2807,7 +2820,7 @@
2807
2820
  overflow: hidden;
2808
2821
  }
2809
2822
 
2810
- .hw-preview-avatar svg {
2823
+ .hw-preview-avatar svg:not(.hw-agent-custom svg) {
2811
2824
  width: 16px;
2812
2825
  height: 16px;
2813
2826
  }
@@ -2903,6 +2916,62 @@
2903
2916
  margin-top: 0;
2904
2917
  }
2905
2918
 
2919
+ /* ── Awaiting-reply marker ───────────────────────────────
2920
+ A state, not an alert. It sits on a row next to product chrome and must not
2921
+ compete with the primary action, so: muted ink, no accent colour, no pill.
2922
+ Labelled rather than counted — a bare number in a coloured badge reads as
2923
+ "unread" and says nothing about what it counts, while these three words say
2924
+ the thing that decides whether the visitor comes back. */
2925
+ .hw-awaiting {
2926
+ margin-top: 2px;
2927
+ padding-left: 44px;
2928
+ font-size: 11px;
2929
+ line-height: 1.4;
2930
+ color: var(--hw-text-3, var(--hw-text-muted));
2931
+ }
2932
+
2933
+ /* ── Closed-state dock ───────────────────────────────────
2934
+ One owner for the strip above the launcher.
2935
+
2936
+ The incoming-reply card and the announcement stack were two independent
2937
+ absolute pins on the same anchor — both `bottom: calc(100% + 12px); right: 0`
2938
+ — so whenever a visitor had an unread reply AND unseen announced content,
2939
+ the two cards drew on top of each other. Neither was readable and the one
2940
+ underneath was unclickable. Nothing in either component could detect the
2941
+ other, which is the tell: the bug is that the region had no owner, not that
2942
+ one of the cards was positioned wrong.
2943
+
2944
+ The dock pins once; its children lay out in flow. Order in the markup is the
2945
+ priority order and it is deliberate — an actual reply from a person sits
2946
+ nearest the launcher, where the thumb already is, and announcements stack
2947
+ above it. Right-aligned rather than stretched because the two cards are
2948
+ different widths (300px vs 340px) and a shared left edge would read as one
2949
+ ragged surface instead of two cards. */
2950
+ .hw-preview-dock {
2951
+ position: absolute;
2952
+ bottom: calc(100% + 12px);
2953
+ right: 0;
2954
+ display: flex;
2955
+ flex-direction: column;
2956
+ align-items: flex-end;
2957
+ gap: 8px;
2958
+ /* Empty dock must not sit over the page. With no children it has zero size,
2959
+ but the gaps between cards are dead space either way — the cards take
2960
+ their own events back below. */
2961
+ pointer-events: none;
2962
+ }
2963
+
2964
+ /* Docked children give up their own pin — two classes, so this wins over the
2965
+ single-class `.hw-preview` / `.hw-preview-stack` rules whatever the source
2966
+ order. */
2967
+ .hw-preview-dock > .hw-preview,
2968
+ .hw-preview-dock > .hw-preview-stack {
2969
+ position: relative;
2970
+ bottom: auto;
2971
+ right: auto;
2972
+ pointer-events: auto;
2973
+ }
2974
+
2906
2975
  /* ── Preview closing animation ──────────────────────────── */
2907
2976
  .hw-preview--closing {
2908
2977
  animation: hw-preview-out 0.2s ease-in forwards;
@@ -2936,6 +3005,30 @@
2936
3005
  width: 100%;
2937
3006
  }
2938
3007
 
3008
+ /* ── Overflow row ────────────────────────────────────────
3009
+ What is left when the announcement stack is clipped. Deliberately not a
3010
+ card: a fourth bordered box would be the volume problem it exists to
3011
+ solve. A single quiet line, right-aligned with the cards above it, that
3012
+ opens the next unread update. */
3013
+ .hw-preview-more {
3014
+ align-self: flex-end;
3015
+ padding: 4px 10px;
3016
+ border: 0;
3017
+ border-radius: 999px;
3018
+ background: var(--hw-bg);
3019
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), inset 0 0 0 1px var(--hw-border);
3020
+ color: var(--hw-text-2);
3021
+ font: inherit;
3022
+ font-size: 12px;
3023
+ line-height: 1.4;
3024
+ cursor: pointer;
3025
+ transition: background 0.12s, color 0.12s;
3026
+ }
3027
+ .hw-preview-more:hover {
3028
+ background: var(--hw-bg-hover);
3029
+ color: var(--hw-text);
3030
+ }
3031
+
2939
3032
  /* ── Announcement preview modifier ─────────────────────── */
2940
3033
  .hw-preview--announcement {
2941
3034
  width: 340px;
@@ -5380,6 +5473,16 @@
5380
5473
  gap: 8px;
5381
5474
  padding: 2px 0 8px;
5382
5475
  }
5476
+ /* Host agent avatar at the bar's start; bottom-aligned with the actions so it
5477
+ stays on the first line's baseline row when the field grows. */
5478
+ .hw-dock-lead {
5479
+ flex: none;
5480
+ display: grid;
5481
+ place-items: center;
5482
+ width: 32px;
5483
+ height: 32px;
5484
+ margin-left: -8px;
5485
+ }
5383
5486
  .hw-dock-actions {
5384
5487
  flex: none;
5385
5488
  display: flex;