@reuters-graphics/graphics-components 3.8.0 → 3.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.
@@ -2,6 +2,7 @@
2
2
  <script lang="ts">
3
3
  import { onDestroy } from 'svelte';
4
4
  import { geocode, type GeocodeFeature, type GeocodeOptions } from './geocode';
5
+ import { normalizeMinLength, normalizeDebounceMs } from './normalize';
5
6
  import MagnifyingGlass from '../SearchInput/components/MagnifyingGlass.svelte';
6
7
  import X from '../SearchInput/components/X.svelte';
7
8
 
@@ -12,12 +13,25 @@
12
13
  searchPlaceholder?: string;
13
14
  /** Callback fired when a location is selected from the results. */
14
15
  onselect?: (location: { lng: number; lat: number; name: string }) => void;
16
+ /**
17
+ * Minimum number of characters before a request is made. Raising this
18
+ * cuts the number of paid geocoding requests per search. Defaults to 2.
19
+ */
20
+ minLength?: number;
21
+ /**
22
+ * Debounce window in milliseconds between the last keystroke and the
23
+ * request. Raising this fires fewer requests while the user is still
24
+ * typing (each request is billed). Defaults to 300.
25
+ */
26
+ debounceMs?: number;
15
27
  }
16
28
 
17
29
  let {
18
30
  accessToken,
19
31
  searchPlaceholder = 'Search for a location',
20
32
  onselect,
33
+ minLength = 2,
34
+ debounceMs = 300,
21
35
  autocomplete = true,
22
36
  bbox,
23
37
  country,
@@ -44,12 +58,22 @@
44
58
  let debounceTimer: ReturnType<typeof setTimeout>;
45
59
  let abortController: AbortController | null = null;
46
60
 
61
+ // Normalize the throttling props so a non-numeric value passed via markup
62
+ // (e.g. `minLength="two"`) can't coerce to NaN and disable the gate — which
63
+ // would bill a request on every keystroke. Fall back to the documented
64
+ // defaults, clamped to sane floors.
65
+ let effectiveMinLength = $derived(normalizeMinLength(minLength));
66
+ let effectiveDebounceMs = $derived(normalizeDebounceMs(debounceMs));
67
+
47
68
  function handleInput() {
48
69
  selectedIndex = -1;
49
70
  clearTimeout(debounceTimer);
50
71
  abortController?.abort();
51
72
 
52
- if (query.length < 2) {
73
+ // Trim first so whitespace-only input (e.g. " ") doesn't clear the gate
74
+ // and bill a request for an empty search.
75
+ const trimmed = query.trim();
76
+ if (trimmed.length < effectiveMinLength) {
53
77
  suggestions = [];
54
78
  return;
55
79
  }
@@ -58,7 +82,7 @@
58
82
  abortController = new AbortController();
59
83
  try {
60
84
  suggestions = await geocode(
61
- query,
85
+ trimmed,
62
86
  {
63
87
  accessToken,
64
88
  autocomplete,
@@ -78,7 +102,7 @@
78
102
  if (e instanceof DOMException && e.name === 'AbortError') return;
79
103
  console.error('Geocoder error:', e);
80
104
  }
81
- }, 300);
105
+ }, effectiveDebounceMs);
82
106
  }
83
107
 
84
108
  onDestroy(() => {
@@ -10,6 +10,17 @@ interface Props extends Omit<GeocodeOptions, 'accessToken'> {
10
10
  lat: number;
11
11
  name: string;
12
12
  }) => void;
13
+ /**
14
+ * Minimum number of characters before a request is made. Raising this
15
+ * cuts the number of paid geocoding requests per search. Defaults to 2.
16
+ */
17
+ minLength?: number;
18
+ /**
19
+ * Debounce window in milliseconds between the last keystroke and the
20
+ * request. Raising this fires fewer requests while the user is still
21
+ * typing (each request is billed). Defaults to 300.
22
+ */
23
+ debounceMs?: number;
13
24
  }
14
25
  /** `Geocoder` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-controls-geocoder--docs) */
15
26
  declare const Geocoder: import("svelte").Component<Props, {}, "">;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Coercion helpers for the Geocoder's request-throttling props.
3
+ *
4
+ * These props can arrive as strings when set via markup (e.g.
5
+ * `minLength="two"`), so a non-numeric value must not be trusted directly: a
6
+ * `NaN` would disable the length gate or the debounce and bill a Mapbox request
7
+ * on every keystroke. Both helpers fall back to the documented defaults and
8
+ * clamp to sane floors.
9
+ */
10
+ /**
11
+ * Coerce a consumer-supplied `minLength` to a safe integer of at least 1.
12
+ * Invalid or sub-1 values fall back to `fallback` (default 2).
13
+ */
14
+ export declare function normalizeMinLength(value: unknown, fallback?: number): number;
15
+ /**
16
+ * Coerce a consumer-supplied `debounceMs` to a finite, non-negative number.
17
+ * Invalid or negative values fall back to `fallback` (default 300).
18
+ */
19
+ export declare function normalizeDebounceMs(value: unknown, fallback?: number): number;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Coercion helpers for the Geocoder's request-throttling props.
3
+ *
4
+ * These props can arrive as strings when set via markup (e.g.
5
+ * `minLength="two"`), so a non-numeric value must not be trusted directly: a
6
+ * `NaN` would disable the length gate or the debounce and bill a Mapbox request
7
+ * on every keystroke. Both helpers fall back to the documented defaults and
8
+ * clamp to sane floors.
9
+ */
10
+ /**
11
+ * Coerce a consumer-supplied `minLength` to a safe integer of at least 1.
12
+ * Invalid or sub-1 values fall back to `fallback` (default 2).
13
+ */
14
+ export function normalizeMinLength(value, fallback = 2) {
15
+ const n = Number(value);
16
+ return Number.isFinite(n) && n >= 1 ? Math.floor(n) : fallback;
17
+ }
18
+ /**
19
+ * Coerce a consumer-supplied `debounceMs` to a finite, non-negative number.
20
+ * Invalid or negative values fall back to `fallback` (default 300).
21
+ */
22
+ export function normalizeDebounceMs(value, fallback = 300) {
23
+ const n = Number(value);
24
+ return Number.isFinite(n) && n >= 0 ? n : fallback;
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reuters-graphics/graphics-components",
3
- "version": "3.8.0",
3
+ "version": "3.10.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "homepage": "https://reuters-graphics.github.io/graphics-components",
@@ -82,12 +82,19 @@
82
82
  "react-colorful": "^5.6.1",
83
83
  "react-dom": "^18.3.1",
84
84
  "react-syntax-highlighter": "^15.6.1",
85
+ "remark-mdx": "^3.1.1",
86
+ "remark-parse": "^11.0.0",
87
+ "remark-stringify": "^11.0.0",
85
88
  "rimraf": "^6.0.1",
86
89
  "sass": "^1.86.3",
87
90
  "storybook": "^8.6.12",
88
91
  "svelte": "^5.28.1",
89
92
  "svelte-check": "^4.1.6",
93
+ "ts-morph": "^28.0.0",
94
+ "tsx": "^4.22.4",
90
95
  "typescript": "^5.8.3",
96
+ "unified": "^11.0.5",
97
+ "unist-util-visit": "^5.1.0",
91
98
  "vite": "^6.3.2"
92
99
  },
93
100
  "dependencies": {
@@ -118,7 +125,19 @@
118
125
  "svelte": "./dist/index.js",
119
126
  "default": "./dist/index.js"
120
127
  },
121
- "./scss/*": "./dist/scss/*"
128
+ "./scss/*": "./dist/scss/*",
129
+ "./llm-docs/*": "./dist/llm-docs/*"
130
+ },
131
+ "llms": {
132
+ "description": [
133
+ "Svelte 5 component library for Reuters Graphics journalism.",
134
+ "Provides components for page layout, text elements, multimedia, maps, and data visualisation,",
135
+ "alongside a full SCSS design system with spacing tokens, typography utilities, colour palettes,",
136
+ "and CSS custom properties for theming."
137
+ ],
138
+ "files": [
139
+ "./dist/llm-docs/**/*"
140
+ ]
122
141
  },
123
142
  "svelte": "./dist/index.js",
124
143
  "types": "./dist/index.d.ts",
@@ -129,7 +148,8 @@
129
148
  "start": "storybook dev -p 3000",
130
149
  "lint": "eslint --fix",
131
150
  "format": "prettier . --write",
132
- "build": "rimraf ./dist && svelte-package -i ./src && publint",
151
+ "generate:llm-docs": "tsx scripts/generate-llm-docs/index.ts",
152
+ "build": "rimraf ./dist && svelte-package -i ./src && pnpm generate:llm-docs && publint",
133
153
  "build:docs": "storybook build -o docs",
134
154
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
135
155
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",