@guardian/interactive-component-library 0.7.16 → 0.7.17

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.
@@ -21,7 +21,9 @@ const PageSection = forwardRef(
21
21
  const headerRef = useRef();
22
22
  useLayoutEffect(() => {
23
23
  const headerElement = headerRef.current;
24
- setMinHeight(headerElement.offsetHeight);
24
+ if (headerElement) {
25
+ setMinHeight(headerElement.offsetHeight);
26
+ }
25
27
  }, [children]);
26
28
  return /* @__PURE__ */ jsxs(
27
29
  "section",
@@ -32,7 +34,7 @@ const PageSection = forwardRef(
32
34
  style: { "--background-color": backgroundColor, minHeight },
33
35
  children: [
34
36
  borderTop && /* @__PURE__ */ jsx("div", { className: styles.borderTop }),
35
- /* @__PURE__ */ jsx(
37
+ children.header && /* @__PURE__ */ jsx(
36
38
  "div",
37
39
  {
38
40
  className: [styles.header, styles[layout]].join(" "),
@@ -1,8 +1,8 @@
1
- const borderTop = "_borderTop_1xpz0_9";
2
- const section = "_section_1xpz0_39";
3
- const fullWidth = "_fullWidth_1xpz0_39";
4
- const header = "_header_1xpz0_150";
5
- const content = "_content_1xpz0_187";
1
+ const borderTop = "_borderTop_1v72w_9";
2
+ const section = "_section_1v72w_39";
3
+ const fullWidth = "_fullWidth_1v72w_39";
4
+ const header = "_header_1v72w_150";
5
+ const content = "_content_1v72w_187";
6
6
  const defaultStyles = {
7
7
  borderTop,
8
8
  section,
@@ -1,2 +1,3 @@
1
1
  export * from './coalitions-tracker';
2
2
  export * from './ticker';
3
+ export { Ticker as Ticker2 } from './ticker-v2';
@@ -0,0 +1,3 @@
1
+ export function Gradient({ position }: {
2
+ position?: string;
3
+ }): import("preact").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
2
+ import defaultStyles from "./style.module.scss.js";
3
+ function Gradient({ position = "left" }) {
4
+ return /* @__PURE__ */ jsxs(
5
+ "svg",
6
+ {
7
+ className: defaultStyles.gradient,
8
+ "data-position": position,
9
+ width: "100%",
10
+ height: "100%",
11
+ viewBox: "0 0 10 10",
12
+ fill: "none",
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ preserveAspectRatio: "none",
15
+ children: [
16
+ /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: "url(#paint0_linear_3798_6653)" }) }),
17
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
18
+ "linearGradient",
19
+ {
20
+ id: "paint0_linear_3798_6653",
21
+ x1: "0%",
22
+ y1: "0%",
23
+ x2: "100%",
24
+ y2: "0%",
25
+ children: position === "left" ? /* @__PURE__ */ jsxs(Fragment, { children: [
26
+ /* @__PURE__ */ jsx("stop", { className: defaultStyles.lastStop, offset: "1" }),
27
+ /* @__PURE__ */ jsx("stop", { className: defaultStyles.firstStop })
28
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
29
+ /* @__PURE__ */ jsx("stop", { className: defaultStyles.firstStop }),
30
+ /* @__PURE__ */ jsx("stop", { className: defaultStyles.lastStop, offset: "1" })
31
+ ] })
32
+ }
33
+ ) })
34
+ ]
35
+ }
36
+ );
37
+ }
38
+ export {
39
+ Gradient
40
+ };
@@ -0,0 +1,5 @@
1
+ export function Ticker({ buttonScrollDistance, styles, children }: {
2
+ buttonScrollDistance?: number;
3
+ styles: any;
4
+ children: any;
5
+ }): import("preact").JSX.Element;
@@ -0,0 +1,103 @@
1
+ import { jsxs, jsx } from "preact/jsx-runtime";
2
+ import { toChildArray } from "preact";
3
+ import { mergeStyles } from "../../../styles/helpers/mergeStyles.js";
4
+ import defaultStyles from "./style.module.scss.js";
5
+ import { Gradient } from "./Gradient.js";
6
+ import { useState, useRef, useEffect } from "preact/hooks";
7
+ import "../../particles/info-button/index.js";
8
+ import "../../particles/relative-time-sentence/index.js";
9
+ import { ArrowButton } from "../../particles/arrow-button/index.js";
10
+ function Ticker({ buttonScrollDistance = 250, styles, children }) {
11
+ styles = mergeStyles({ ...defaultStyles }, styles);
12
+ const [isScrolledToStart, setIsScrolledToStart] = useState(true);
13
+ const [isScrolledToEnd, setIsScrolledToEnd] = useState(false);
14
+ const [isOverflow, setIsOverflow] = useState(false);
15
+ const childArray = toChildArray(children);
16
+ const scrollContainerRef = useRef(null);
17
+ function scrubLeft() {
18
+ const scrollContainer = scrollContainerRef.current;
19
+ if (!scrollContainer) return;
20
+ let newScrollLeft = scrollContainer.scrollLeft - buttonScrollDistance;
21
+ if (newScrollLeft < 100) {
22
+ newScrollLeft = 0;
23
+ }
24
+ scrollContainer.scrollTo({
25
+ left: newScrollLeft,
26
+ behavior: "smooth"
27
+ });
28
+ }
29
+ function scrubRight() {
30
+ const scrollContainer = scrollContainerRef.current;
31
+ if (!scrollContainer) return;
32
+ let scrollSpace = scrollContainer.scrollWidth - scrollContainer.clientWidth;
33
+ let newScrollLeft = scrollContainer.scrollLeft + buttonScrollDistance;
34
+ if (newScrollLeft > scrollSpace - 100) {
35
+ newScrollLeft = scrollSpace + 1;
36
+ }
37
+ scrollContainer.scrollTo({
38
+ left: newScrollLeft,
39
+ behavior: "smooth"
40
+ });
41
+ }
42
+ useEffect(() => {
43
+ const scrollContainer = scrollContainerRef.current;
44
+ if (!scrollContainer) return;
45
+ let scrollDebounceTimeout;
46
+ const handleScroll = () => {
47
+ clearTimeout(scrollDebounceTimeout);
48
+ scrollDebounceTimeout = setTimeout(() => {
49
+ const currentScroll = scrollContainer.scrollLeft;
50
+ const scrollSpace = scrollContainer.scrollWidth - scrollContainer.clientWidth - 4;
51
+ setIsScrolledToEnd(currentScroll > scrollSpace);
52
+ setIsScrolledToStart(currentScroll === 0);
53
+ }, 20);
54
+ };
55
+ scrollContainer.addEventListener("scroll", handleScroll);
56
+ return () => {
57
+ clearTimeout(scrollDebounceTimeout);
58
+ scrollContainer.removeEventListener("scroll", handleScroll);
59
+ };
60
+ }, []);
61
+ useEffect(() => {
62
+ const scrollContainer = scrollContainerRef.current;
63
+ if (!scrollContainer) return;
64
+ if (scrollContainer.scrollWidth > scrollContainer.clientWidth) {
65
+ setIsOverflow(true);
66
+ }
67
+ }, [children]);
68
+ return /* @__PURE__ */ jsxs("div", { className: styles.ticker, children: [
69
+ /* @__PURE__ */ jsx("div", { ref: scrollContainerRef, className: styles.scrollContainer, children: childArray.map((child, index) => {
70
+ var _a;
71
+ return /* @__PURE__ */ jsx("div", { className: styles.tickerItem, children: child }, ((_a = child.props) == null ? void 0 : _a.id) ?? index);
72
+ }) }),
73
+ /* @__PURE__ */ jsxs(
74
+ "div",
75
+ {
76
+ className: `${styles.scrubControls} ${isOverflow ? styles.showControls : ""}`,
77
+ children: [
78
+ /* @__PURE__ */ jsx(Gradient, { position: "right" }),
79
+ /* @__PURE__ */ jsx(
80
+ ArrowButton,
81
+ {
82
+ styles: { button: styles.arrowButton },
83
+ onClick: scrubRight,
84
+ disabled: isScrolledToEnd
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx(
88
+ ArrowButton,
89
+ {
90
+ styles: { button: styles.arrowButton },
91
+ direction: "left",
92
+ onClick: scrubLeft,
93
+ disabled: isScrolledToStart
94
+ }
95
+ )
96
+ ]
97
+ }
98
+ )
99
+ ] });
100
+ }
101
+ export {
102
+ Ticker
103
+ };
@@ -0,0 +1,32 @@
1
+ const ticker = "_ticker_1pk9n_9";
2
+ const scrollContainer = "_scrollContainer_1pk9n_14";
3
+ const tickerItem = "_tickerItem_1pk9n_39";
4
+ const scrubControls = "_scrubControls_1pk9n_43";
5
+ const showControls = "_showControls_1pk9n_53";
6
+ const arrowButton = "_arrowButton_1pk9n_62";
7
+ const gradient = "_gradient_1pk9n_66";
8
+ const firstStop = "_firstStop_1pk9n_81";
9
+ const lastStop = "_lastStop_1pk9n_86";
10
+ const defaultStyles = {
11
+ ticker,
12
+ scrollContainer,
13
+ tickerItem,
14
+ scrubControls,
15
+ showControls,
16
+ arrowButton,
17
+ gradient,
18
+ firstStop,
19
+ lastStop
20
+ };
21
+ export {
22
+ arrowButton,
23
+ defaultStyles as default,
24
+ firstStop,
25
+ gradient,
26
+ lastStop,
27
+ scrollContainer,
28
+ scrubControls,
29
+ showControls,
30
+ ticker,
31
+ tickerItem
32
+ };
package/dist/index.js CHANGED
@@ -61,6 +61,7 @@ import "./components/molecules/canvas-map/Map.js";
61
61
  import { OptionPicker } from "./components/molecules/option-picker/index.js";
62
62
  import { CoalitionsTracker } from "./components/organisms/coalitions-tracker/index.js";
63
63
  import { Ticker } from "./components/organisms/ticker/index.js";
64
+ import { Ticker as Ticker2 } from "./components/organisms/ticker-v2/index.js";
64
65
  import { useContainerSize } from "./shared/hooks/useContainerSize.js";
65
66
  import { useTouchOrHover } from "./shared/hooks/useTouchOrHover.js";
66
67
  import { useWindowSize } from "./shared/hooks/useWindowSize.js";
@@ -124,6 +125,7 @@ export {
124
125
  Text,
125
126
  TextLayer,
126
127
  Ticker,
128
+ Ticker2,
127
129
  Tooltip,
128
130
  ToplineResult,
129
131
  VectorLayer,
package/dist/style.css CHANGED
@@ -2186,79 +2186,79 @@ body.android {
2186
2186
  --top-inset: 58px;
2187
2187
  }
2188
2188
 
2189
- ._borderTop_1xpz0_9 {
2189
+ ._borderTop_1v72w_9 {
2190
2190
  border-top: 1px solid var(--border-divider-color);
2191
2191
  transform: translate(-10px);
2192
2192
  width: calc(100% + 20px);
2193
2193
  }
2194
2194
  @media (min-width: 30em) {
2195
- ._borderTop_1xpz0_9 {
2195
+ ._borderTop_1v72w_9 {
2196
2196
  transform: translate(-20px);
2197
2197
  width: calc(100% + 40px);
2198
2198
  }
2199
2199
  }
2200
2200
  @media (min-width: 46.25em) {
2201
- ._borderTop_1xpz0_9 {
2201
+ ._borderTop_1v72w_9 {
2202
2202
  width: calc(100% + 40px);
2203
2203
  }
2204
2204
  }
2205
2205
  @media (min-width: 71.25em) {
2206
- ._borderTop_1xpz0_9 {
2206
+ ._borderTop_1v72w_9 {
2207
2207
  transform: translate(-180px);
2208
2208
  width: calc(100% + 197px);
2209
2209
  background-color: transparent;
2210
2210
  }
2211
2211
  }
2212
2212
  @media (min-width: 81.25em) {
2213
- ._borderTop_1xpz0_9 {
2213
+ ._borderTop_1v72w_9 {
2214
2214
  transform: translate(-260px);
2215
2215
  width: calc(100% + 279px);
2216
2216
  }
2217
2217
  }
2218
2218
 
2219
- ._section_1xpz0_39._fullWidth_1xpz0_39 ._borderTop_1xpz0_9 {
2219
+ ._section_1v72w_39._fullWidth_1v72w_39 ._borderTop_1v72w_9 {
2220
2220
  transform: none;
2221
2221
  width: calc(100% - 1px);
2222
2222
  }
2223
2223
 
2224
- ._section_1xpz0_39 {
2224
+ ._section_1v72w_39 {
2225
2225
  position: relative;
2226
2226
  z-index: 0;
2227
2227
  padding-bottom: var(--space-8);
2228
2228
  }
2229
2229
 
2230
- ._section_1xpz0_39._fullWidth_1xpz0_39 {
2230
+ ._section_1v72w_39._fullWidth_1v72w_39 {
2231
2231
  transform: translate(-10px);
2232
2232
  width: calc(100% + 20px);
2233
2233
  margin: 0;
2234
2234
  padding: 0;
2235
2235
  }
2236
2236
  @media (min-width: 30em) {
2237
- ._section_1xpz0_39._fullWidth_1xpz0_39 {
2237
+ ._section_1v72w_39._fullWidth_1v72w_39 {
2238
2238
  transform: translate(-20px);
2239
2239
  width: calc(100% + 40px);
2240
2240
  }
2241
2241
  }
2242
2242
  @media (min-width: 46.25em) {
2243
- ._section_1xpz0_39._fullWidth_1xpz0_39 {
2243
+ ._section_1v72w_39._fullWidth_1v72w_39 {
2244
2244
  transform: translate(-20px);
2245
2245
  width: calc(100% + 40px);
2246
2246
  }
2247
2247
  }
2248
2248
  @media (min-width: 71.25em) {
2249
- ._section_1xpz0_39._fullWidth_1xpz0_39 {
2249
+ ._section_1v72w_39._fullWidth_1v72w_39 {
2250
2250
  transform: translate(-180px);
2251
2251
  width: calc(100% + 197px);
2252
2252
  }
2253
2253
  }
2254
2254
  @media (min-width: 81.25em) {
2255
- ._section_1xpz0_39._fullWidth_1xpz0_39 {
2255
+ ._section_1v72w_39._fullWidth_1v72w_39 {
2256
2256
  transform: translate(-260px);
2257
2257
  width: calc(100% + 280px);
2258
2258
  }
2259
2259
  }
2260
2260
 
2261
- ._section_1xpz0_39::before {
2261
+ ._section_1v72w_39::before {
2262
2262
  display: block;
2263
2263
  content: "";
2264
2264
  position: absolute;
@@ -2271,29 +2271,29 @@ body.android {
2271
2271
  background-color: var(--background-color);
2272
2272
  }
2273
2273
  @media (min-width: 30em) {
2274
- ._section_1xpz0_39::before {
2274
+ ._section_1v72w_39::before {
2275
2275
  transform: translate(-20px);
2276
2276
  width: calc(100% + 40px);
2277
2277
  }
2278
2278
  }
2279
2279
  @media (min-width: 46.25em) {
2280
- ._section_1xpz0_39::before {
2280
+ ._section_1v72w_39::before {
2281
2281
  width: calc(100% + 40px);
2282
2282
  }
2283
2283
  }
2284
2284
  @media (min-width: 71.25em) {
2285
- ._section_1xpz0_39::before {
2285
+ ._section_1v72w_39::before {
2286
2286
  transform: translateX(-9px);
2287
2287
  width: calc(100% + 26px);
2288
2288
  }
2289
2289
  }
2290
2290
  @media (min-width: 81.25em) {
2291
- ._section_1xpz0_39::before {
2291
+ ._section_1v72w_39::before {
2292
2292
  width: calc(100% + 27px);
2293
2293
  }
2294
2294
  }
2295
2295
 
2296
- ._section_1xpz0_39._fullWidth_1xpz0_39::before {
2296
+ ._section_1v72w_39._fullWidth_1v72w_39::before {
2297
2297
  transform: none;
2298
2298
  width: calc(100% - 3px);
2299
2299
  height: 100%;
@@ -2303,38 +2303,38 @@ body.android {
2303
2303
  width: calc(100% + 20px);
2304
2304
  }
2305
2305
  @media (min-width: 30em) {
2306
- ._section_1xpz0_39._fullWidth_1xpz0_39::before {
2306
+ ._section_1v72w_39._fullWidth_1v72w_39::before {
2307
2307
  transform: translate(-20px);
2308
2308
  width: calc(100% + 40px);
2309
2309
  }
2310
2310
  }
2311
2311
  @media (min-width: 46.25em) {
2312
- ._section_1xpz0_39._fullWidth_1xpz0_39::before {
2312
+ ._section_1v72w_39._fullWidth_1v72w_39::before {
2313
2313
  width: 100%;
2314
2314
  transform: translateX(-1px);
2315
2315
  }
2316
2316
  }
2317
2317
  @media (min-width: 71.25em) {
2318
- ._section_1xpz0_39._fullWidth_1xpz0_39::before {
2318
+ ._section_1v72w_39._fullWidth_1v72w_39::before {
2319
2319
  transform: translateX(-1px);
2320
2320
  width: 100%;
2321
2321
  }
2322
2322
  }
2323
2323
  @media (min-width: 81.25em) {
2324
- ._section_1xpz0_39._fullWidth_1xpz0_39::before {
2324
+ ._section_1v72w_39._fullWidth_1v72w_39::before {
2325
2325
  transform: none;
2326
2326
  width: calc(100% - 3px);
2327
2327
  }
2328
2328
  }
2329
2329
 
2330
- ._header_1xpz0_150 {
2330
+ ._header_1v72w_150 {
2331
2331
  color: var(--primary-text-color);
2332
2332
  padding-top: var(--space-2);
2333
2333
  margin-bottom: var(--space-5);
2334
2334
  }
2335
2335
 
2336
2336
  @media (min-width: 71.25em) {
2337
- body:not(.ios, .android) ._header_1xpz0_150 {
2337
+ body:not(.ios, .android) ._header_1v72w_150 {
2338
2338
  position: absolute;
2339
2339
  max-width: 160px;
2340
2340
  transform: translateX(-170px);
@@ -2342,13 +2342,13 @@ body.android {
2342
2342
  }
2343
2343
  }
2344
2344
  @media (min-width: 81.25em) {
2345
- body:not(.ios, .android) ._header_1xpz0_150 {
2345
+ body:not(.ios, .android) ._header_1v72w_150 {
2346
2346
  max-width: 220px;
2347
2347
  transform: translateX(-250px);
2348
2348
  }
2349
2349
  }
2350
2350
 
2351
- body ._header_1xpz0_150._fullWidth_1xpz0_39 {
2351
+ body ._header_1v72w_150._fullWidth_1v72w_39 {
2352
2352
  position: absolute;
2353
2353
  top: 0;
2354
2354
  left: 0;
@@ -2359,28 +2359,32 @@ body ._header_1xpz0_150._fullWidth_1xpz0_39 {
2359
2359
  max-width: 100%;
2360
2360
  }
2361
2361
  @media (min-width: 71.25em) {
2362
- body ._header_1xpz0_150._fullWidth_1xpz0_39 {
2362
+ body ._header_1v72w_150._fullWidth_1v72w_39 {
2363
2363
  margin-bottom: 0;
2364
2364
  }
2365
2365
  }
2366
2366
 
2367
- ._content_1xpz0_187 {
2367
+ ._content_1v72w_187 {
2368
2368
  position: relative;
2369
2369
  padding-top: 0;
2370
2370
  z-index: 0;
2371
2371
  color: var(--primary-text-color);
2372
2372
  }
2373
2373
  @media (min-width: 71.25em) {
2374
- ._content_1xpz0_187 {
2374
+ ._content_1v72w_187 {
2375
2375
  padding-top: var(--space-2);
2376
2376
  }
2377
2377
  }
2378
2378
 
2379
- ._content_1xpz0_187._fullWidth_1xpz0_39 {
2379
+ :not(._header_1v72w_150) + ._content_1v72w_187 {
2380
+ padding-top: var(--space-2);
2381
+ }
2382
+
2383
+ ._content_1v72w_187._fullWidth_1v72w_39 {
2380
2384
  padding-top: 0;
2381
2385
  }
2382
2386
 
2383
- ._content_1xpz0_187._fullWidth_1xpz0_39::before {
2387
+ ._content_1v72w_187._fullWidth_1v72w_39::before {
2384
2388
  display: none;
2385
2389
  }._text_1ci1k_1 {
2386
2390
  font-family: var(--text-sans);
@@ -3413,4 +3417,92 @@ body.android {
3413
3417
  left: 0;
3414
3418
  bottom: 0;
3415
3419
  padding-bottom: 8px;
3420
+ }body {
3421
+ --top-inset: 0;
3422
+ }
3423
+
3424
+ body.android {
3425
+ --top-inset: 58px;
3426
+ }
3427
+
3428
+ ._ticker_1pk9n_9 {
3429
+ width: 100%;
3430
+ position: relative;
3431
+ }
3432
+
3433
+ ._scrollContainer_1pk9n_14 {
3434
+ position: relative;
3435
+ padding: 0;
3436
+ cursor: default;
3437
+ display: flex;
3438
+ flex-direction: row;
3439
+ gap: var(--space-2);
3440
+ overflow-x: scroll;
3441
+ }
3442
+ @media (max-width: 29.99em) {
3443
+ ._scrollContainer_1pk9n_14 {
3444
+ /* Make room for bottom scroll bar */
3445
+ padding-bottom: 8px;
3446
+ }
3447
+ }
3448
+ @media (min-width: 30em) {
3449
+ ._scrollContainer_1pk9n_14 {
3450
+ /* Make room for the scrub controls */
3451
+ padding-right: 36px;
3452
+ }
3453
+ ._scrollContainer_1pk9n_14::-webkit-scrollbar {
3454
+ display: none; /* for Chrome, Safari, and Opera */
3455
+ }
3456
+ }
3457
+
3458
+ ._tickerItem_1pk9n_39 {
3459
+ flex-shrink: 0;
3460
+ }
3461
+
3462
+ ._scrubControls_1pk9n_43 {
3463
+ position: absolute;
3464
+ right: 0;
3465
+ top: 0;
3466
+ height: 100%;
3467
+ flex-direction: column;
3468
+ justify-content: center;
3469
+ display: none;
3470
+ }
3471
+
3472
+ ._scrubControls_1pk9n_43._showControls_1pk9n_53 {
3473
+ display: flex;
3474
+ }
3475
+ @media (max-width: 29.99em) {
3476
+ ._scrubControls_1pk9n_43._showControls_1pk9n_53 {
3477
+ display: none;
3478
+ }
3479
+ }
3480
+
3481
+ ._arrowButton_1pk9n_62 {
3482
+ z-index: 1;
3483
+ }
3484
+
3485
+ ._gradient_1pk9n_66 {
3486
+ position: absolute;
3487
+ top: 0;
3488
+ bottom: 0;
3489
+ width: 40px;
3490
+ }
3491
+
3492
+ ._gradient_1pk9n_66[data-position=left] {
3493
+ left: 0;
3494
+ }
3495
+
3496
+ ._gradient_1pk9n_66[data-position=right] {
3497
+ right: 0;
3498
+ }
3499
+
3500
+ ._firstStop_1pk9n_81 {
3501
+ stop-color: var(--tertiary-bg-color);
3502
+ stop-opacity: 0;
3503
+ }
3504
+
3505
+ ._lastStop_1pk9n_86 {
3506
+ stop-color: var(--tertiary-bg-color);
3507
+ stop-opacity: 1;
3416
3508
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@guardian/interactive-component-library",
3
3
  "private": false,
4
- "version": "0.7.16",
4
+ "version": "0.7.17",
5
5
  "packageManager": "pnpm@8.4.0",
6
6
  "repository": {
7
7
  "type": "git",