@windstream/react-shared-components 0.2.64 → 0.2.65

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.d.ts CHANGED
@@ -70,7 +70,7 @@ declare const Input: React$1.ForwardRefExoticComponent<Omit<React$1.InputHTMLAtt
70
70
  size?: "slim" | "medium" | "large" | undefined;
71
71
  label?: string | undefined;
72
72
  errorText?: string | undefined;
73
- prefixIconName?: "location_on" | "search" | undefined;
73
+ prefixIconName?: "search" | "location_on" | undefined;
74
74
  prefixIconSize?: 20 | 24 | 40 | 48 | undefined;
75
75
  prefixIconFill?: boolean | undefined;
76
76
  suffixIconFill?: boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windstream/react-shared-components",
3
- "version": "0.2.64",
3
+ "version": "0.2.65",
4
4
  "type": "module",
5
5
  "description": "Shared React components for Kinetic applications",
6
6
  "main": "dist/index.js",
@@ -178,18 +178,27 @@ export const AnchoredBottomBanner: React.FC<AnchoredBottomBannerProps> = ({
178
178
  const [nowMs, setNowMs] = useState(() => Date.now());
179
179
  const intervalRef = useRef<number | null>(null);
180
180
 
181
+ const [hasMounted, setHasMounted] = useState(false);
182
+ useEffect(() => setHasMounted(true), []);
183
+
181
184
  // The message active for "now" (display window + daysToShow) wins.
182
185
  const activeMessage = useMemo(
183
- () => scheduledMessages?.find(message => isMessageActive(message, nowMs)),
184
- [scheduledMessages, nowMs]
186
+ () =>
187
+ hasMounted
188
+ ? scheduledMessages?.find(message => isMessageActive(message, nowMs))
189
+ : undefined,
190
+ [scheduledMessages, nowMs, hasMounted]
185
191
  );
186
192
  const hasActiveMessage = activeMessage !== undefined;
187
193
 
188
194
  // Expose the resolved result so consumers (analytics) can read what showed.
189
195
  const applicableWeekday = schedulingZoneWeekday(nowMs);
190
196
  useEffect(() => {
197
+ // Only report after client-side schedule resolution so analytics never
198
+ // records the pre-mount hasActiveMessage:false fallback.
199
+ if (!hasMounted) return;
191
200
  onResolved?.({ hasActiveMessage, activeMessage, applicableWeekday });
192
- }, [hasActiveMessage, activeMessage, applicableWeekday, onResolved]);
201
+ }, [hasMounted, hasActiveMessage, activeMessage, applicableWeekday, onResolved]);
193
202
 
194
203
  // Latest display-window end, so we keep ticking to let messages activate/expire.
195
204
  const scheduleMaxEndMs = useMemo(() => {
@@ -328,12 +337,12 @@ export const AnchoredBottomBanner: React.FC<AnchoredBottomBannerProps> = ({
328
337
  className={`${textColorClass} align-text-bottom`}
329
338
  />
330
339
  )}
331
- {countdown.shouldShow && (
340
+ {hasMounted && countdown.shouldShow && (
332
341
  <span className="inline-block whitespace-nowrap rounded-lg bg-white px-1 tabular-nums text-text">
333
342
  {countdown.text}
334
343
  </span>
335
344
  )}
336
- {countdown.shouldShow ? " " : null}
345
+ {hasMounted && countdown.shouldShow ? " " : null}
337
346
  {effectiveCtaButtonLabel && effectiveCtaButtonLabel}{" "}
338
347
  {effectiveCtaSuffixText && (
339
348
  <span className="ml-0.5">{effectiveCtaSuffixText}</span>
@@ -205,6 +205,23 @@ describe("Footer", () => {
205
205
  });
206
206
 
207
207
  describe("Copyright and terms", () => {
208
+ it("wraps copyrights in a <div> (not a <p>) so block-level rich text is valid", () => {
209
+ render(<Footer {...defaultProps} />);
210
+ const copyEl = screen.getByText("All rights reserved.");
211
+ expect(copyEl.tagName).toBe("DIV");
212
+ });
213
+
214
+ it("renders block-level rich text in copyrights without invalid <div>-in-<p> nesting", () => {
215
+ render(
216
+ <Footer
217
+ {...defaultProps}
218
+ copyrights={<div data-testid="rich-copyright">© 2026 Windstream</div>}
219
+ />
220
+ );
221
+ // the rich-text <div> must NOT be nested inside a <p>
222
+ expect(screen.getByTestId("rich-copyright").closest("p")).toBeNull();
223
+ });
224
+
208
225
  it("renders copyright year with current year", () => {
209
226
  render(<Footer {...defaultProps} />);
210
227
  const currentYear = new Date().getFullYear().toString();
@@ -64,7 +64,7 @@ export const Footer: React.FC<FooterProps> = ({
64
64
  <p className="terms-text footnote text-white">
65
65
  &copy; {new Date().getFullYear()} {terms}
66
66
  </p>
67
- <p className="copy-rights whitespace-pre-line">{copyrights}</p>
67
+ <div className="copy-rights whitespace-pre-line">{copyrights}</div>
68
68
  <nav aria-label="Footer legal">
69
69
  <ul className="bottom-links list-none">
70
70
  {bottomLinks?.map((link: any, index: number) => (