@communitiesuk/svelte-component-library 0.1.19-beta.1 → 0.1.19-beta.3
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/components/data-vis/position-chart/PositionChart.svelte +74 -75
- package/dist/components/data-vis/position-chart/PositionChart.svelte.d.ts +4 -0
- package/dist/components/ui/Card.svelte +4 -0
- package/dist/components/ui/PostcodeOrAreaSearch.svelte +12 -0
- package/dist/components/ui/PostcodeOrAreaSearch.svelte.d.ts +4 -0
- package/dist/components/ui/SearchAutocomplete.svelte +156 -30
- package/dist/components/ui/SearchAutocomplete.svelte.d.ts +4 -0
- package/package.json +1 -1
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { scaleLinear } from "d3-scale";
|
|
3
3
|
import PositionChartAxis from "./PositionChartAxis.svelte";
|
|
4
4
|
import ValueLabel from "../line-chart/ValueLabel.svelte";
|
|
5
|
+
import Button from "../../ui/Button.svelte";
|
|
6
|
+
import InsetText from "../../content/InsetText.svelte";
|
|
5
7
|
let {
|
|
6
8
|
value = undefined,
|
|
7
9
|
min = undefined,
|
|
@@ -20,6 +22,8 @@
|
|
|
20
22
|
annotation = undefined,
|
|
21
23
|
showIcon = false,
|
|
22
24
|
moreInfo = undefined,
|
|
25
|
+
markerRadius = chartHeight / 2,
|
|
26
|
+
options = [],
|
|
23
27
|
rowData = [
|
|
24
28
|
{
|
|
25
29
|
value: value,
|
|
@@ -117,16 +121,12 @@
|
|
|
117
121
|
}),
|
|
118
122
|
);
|
|
119
123
|
|
|
120
|
-
$
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
let openStates = $state({});
|
|
124
|
+
let moreInfoTogglesArray = $state(
|
|
125
|
+
Array.from({ length: options.length }, () => false),
|
|
126
|
+
);
|
|
124
127
|
|
|
125
|
-
function
|
|
126
|
-
|
|
127
|
-
...openStates,
|
|
128
|
-
[label]: !openStates[label], // flip true/false
|
|
129
|
-
};
|
|
128
|
+
function updateMoreInfoTogglesArray(index) {
|
|
129
|
+
moreInfoTogglesArray[index] = !moreInfoTogglesArray[index];
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
let showLabel = $derived(
|
|
@@ -224,9 +224,6 @@
|
|
|
224
224
|
return result;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
// the 'marker' is the circle
|
|
228
|
-
let markerRadius = $derived(chartHeight / 2);
|
|
229
|
-
|
|
230
227
|
// the 'bar' is the 10 rectangles side by side
|
|
231
228
|
let barWidth = $derived(chartWidth - markerRadius * 2);
|
|
232
229
|
let barHeight = $derived((chartHeight * 5) / 6);
|
|
@@ -308,13 +305,22 @@
|
|
|
308
305
|
>
|
|
309
306
|
{#each allDataNormalized as positionChart, i}
|
|
310
307
|
{#if showLabel}
|
|
311
|
-
<p
|
|
308
|
+
<p
|
|
309
|
+
class="govuk-body-s"
|
|
310
|
+
style=" text-align: right;
|
|
311
|
+
margin: 0;
|
|
312
|
+
line-height: 1.05;"
|
|
313
|
+
>
|
|
314
|
+
{positionChart.label}
|
|
315
|
+
</p>
|
|
312
316
|
{/if}
|
|
313
317
|
{#if showIcon}
|
|
314
|
-
<
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
+
<Button
|
|
319
|
+
textContent="i"
|
|
320
|
+
buttonType="moreInfo"
|
|
321
|
+
noPadding={true}
|
|
322
|
+
onClickFunction={() => updateMoreInfoTogglesArray(i)}
|
|
323
|
+
></Button>
|
|
318
324
|
{/if}
|
|
319
325
|
<div
|
|
320
326
|
class="chart"
|
|
@@ -340,70 +346,68 @@
|
|
|
340
346
|
>{/each}
|
|
341
347
|
{#each Object.entries(positionChart.rowData) as [tier, points]}
|
|
342
348
|
{#each points as rowValue, i}
|
|
343
|
-
{
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
349
|
+
{#if !isNaN(Number(rowValue.value))}
|
|
350
|
+
{@const markerId = "marker-" + rowValue.value}
|
|
351
|
+
<g
|
|
352
|
+
data-id={markerId}
|
|
353
|
+
onclick={interactiveMarkers
|
|
354
|
+
? (event) => onClickMarker(event, rowValue, markerId)
|
|
355
|
+
: null}
|
|
356
|
+
onmouseenter={interactiveMarkers
|
|
357
|
+
? (event) =>
|
|
358
|
+
onMouseEnterMarker(
|
|
359
|
+
event,
|
|
360
|
+
rowValue,
|
|
361
|
+
markerId,
|
|
362
|
+
event.currentTarget.getBoundingClientRect(),
|
|
363
|
+
)
|
|
364
|
+
: null}
|
|
365
|
+
onmouseleave={interactiveMarkers
|
|
366
|
+
? (event) => onMouseLeaveMarker(event, rowValue, markerId)
|
|
367
|
+
: null}
|
|
368
|
+
role="button"
|
|
369
|
+
tabindex="0"
|
|
370
|
+
onkeydown={interactiveMarkers
|
|
371
|
+
? (e) => e.key === "Enter" && onClickMarker(e, value)
|
|
372
|
+
: null}
|
|
373
|
+
pointer-events={interactiveMarkers ? null : "none"}
|
|
374
|
+
transform="translate({xFunction(
|
|
375
|
+
positionChart.min,
|
|
376
|
+
positionChart.max,
|
|
377
|
+
)(rowValue.value) + markerRadius},{positionChart.chartHeight /
|
|
378
|
+
2})"
|
|
379
|
+
>
|
|
380
|
+
<circle
|
|
381
|
+
r={markerRadius}
|
|
382
|
+
cx="0"
|
|
383
|
+
cy="0"
|
|
384
|
+
fill={rowValue.colour}
|
|
385
|
+
stroke="white"
|
|
386
|
+
opacity={rowValue.opacity}
|
|
387
|
+
></circle>
|
|
388
|
+
</g>
|
|
389
|
+
{/if}
|
|
382
390
|
{/each}
|
|
383
391
|
{/each}
|
|
384
392
|
</svg>
|
|
385
393
|
</div>
|
|
386
|
-
{#if
|
|
387
|
-
<div
|
|
388
|
-
class="
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
<p>
|
|
392
|
-
{positionChart.moreInfo}
|
|
393
|
-
</p>
|
|
394
|
+
{#if moreInfoTogglesArray[i]}
|
|
395
|
+
<div class="accordion" style="grid-column:1 / -1;">
|
|
396
|
+
<p class="govuk-body-s">{positionChart.moreInfo}</p>
|
|
397
|
+
<!-- <InsetText content={positionChart.moreInfo} renderStringAsHTML={true}
|
|
398
|
+
></InsetText> -->
|
|
394
399
|
</div>
|
|
395
400
|
{/if}
|
|
396
401
|
{#if positionChart.divider}
|
|
397
402
|
<div style="grid-column:1 / -1">
|
|
398
|
-
<svg width="100%" height="
|
|
403
|
+
<svg width="100%" height="5">
|
|
399
404
|
<line
|
|
400
405
|
x1="0"
|
|
401
|
-
y1="5"
|
|
406
|
+
y1="2.5"
|
|
402
407
|
x2="100%"
|
|
403
|
-
y2="
|
|
404
|
-
stroke="
|
|
405
|
-
stroke-width="
|
|
406
|
-
stroke-dasharray="2,6"
|
|
408
|
+
y2="2.55"
|
|
409
|
+
stroke="grey"
|
|
410
|
+
stroke-width="0.5"
|
|
407
411
|
></line>
|
|
408
412
|
</svg>
|
|
409
413
|
</div>{/if}
|
|
@@ -445,11 +449,6 @@
|
|
|
445
449
|
column-gap: 2%;
|
|
446
450
|
row-gap: 2%;
|
|
447
451
|
}
|
|
448
|
-
.label {
|
|
449
|
-
text-align: right;
|
|
450
|
-
margin: 0;
|
|
451
|
-
line-height: 1.05;
|
|
452
|
-
}
|
|
453
452
|
.chart {
|
|
454
453
|
display: flex;
|
|
455
454
|
flex-direction: column;
|
|
@@ -21,6 +21,8 @@ declare const PositionChart: import("svelte").Component<{
|
|
|
21
21
|
annotation?: any;
|
|
22
22
|
showIcon?: boolean;
|
|
23
23
|
moreInfo?: any;
|
|
24
|
+
markerRadius?: any;
|
|
25
|
+
options?: any[];
|
|
24
26
|
rowData?: any[];
|
|
25
27
|
allData?: any[];
|
|
26
28
|
markerStyles?: Record<string, any>;
|
|
@@ -59,6 +61,8 @@ type $$ComponentProps = {
|
|
|
59
61
|
annotation?: any;
|
|
60
62
|
showIcon?: boolean;
|
|
61
63
|
moreInfo?: any;
|
|
64
|
+
markerRadius?: any;
|
|
65
|
+
options?: any[];
|
|
62
66
|
rowData?: any[];
|
|
63
67
|
allData?: any[];
|
|
64
68
|
markerStyles?: Record<string, any>;
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
homepage?: boolean;
|
|
58
58
|
minLength?: number;
|
|
59
59
|
required?: boolean;
|
|
60
|
+
autoselect?: boolean; // Auto-highlight first suggestion
|
|
61
|
+
hideHint?: boolean; // Hide the hint input element when autoselect is true
|
|
62
|
+
prefixMatchOnly?: boolean; // Only show suggestions that start with the query
|
|
63
|
+
autoFocusSubmitOnSelection?: boolean; // Auto-focus submit button when selection is confirmed
|
|
60
64
|
[key: string]: any; // Allow other props
|
|
61
65
|
};
|
|
62
66
|
|
|
@@ -83,6 +87,10 @@
|
|
|
83
87
|
homepage = false,
|
|
84
88
|
minLength = 2,
|
|
85
89
|
required = false,
|
|
90
|
+
autoselect = true,
|
|
91
|
+
hideHint = false,
|
|
92
|
+
prefixMatchOnly = false,
|
|
93
|
+
autoFocusSubmitOnSelection = false,
|
|
86
94
|
...restProps
|
|
87
95
|
}: Props = $props();
|
|
88
96
|
|
|
@@ -222,6 +230,10 @@
|
|
|
222
230
|
homepage,
|
|
223
231
|
minLength,
|
|
224
232
|
required,
|
|
233
|
+
autoselect,
|
|
234
|
+
hideHint,
|
|
235
|
+
prefixMatchOnly,
|
|
236
|
+
autoFocusSubmitOnSelection,
|
|
225
237
|
...restProps,
|
|
226
238
|
});
|
|
227
239
|
</script>
|
|
@@ -31,6 +31,10 @@ type Props = {
|
|
|
31
31
|
homepage?: boolean;
|
|
32
32
|
minLength?: number;
|
|
33
33
|
required?: boolean;
|
|
34
|
+
autoselect?: boolean;
|
|
35
|
+
hideHint?: boolean;
|
|
36
|
+
prefixMatchOnly?: boolean;
|
|
37
|
+
autoFocusSubmitOnSelection?: boolean;
|
|
34
38
|
[key: string]: any;
|
|
35
39
|
};
|
|
36
40
|
declare const PostcodeOrAreaSearch: import("svelte").Component<Props, {}, "selectedValue">;
|
|
@@ -51,6 +51,10 @@
|
|
|
51
51
|
hint?: string; // Add hint prop
|
|
52
52
|
selectedValue?: any; // Bindable selected value, updated on selection
|
|
53
53
|
maxSuggestions?: number; // Maximum number of suggestions to display
|
|
54
|
+
autoselect?: boolean; // Auto-highlight first suggestion
|
|
55
|
+
hideHint?: boolean; // Hide the hint input element when autoselect is true
|
|
56
|
+
prefixMatchOnly?: boolean; // Only show suggestions that start with the query (better for hint behavior)
|
|
57
|
+
autoFocusSubmitOnSelection?: boolean; // Auto-focus submit button when selection is confirmed
|
|
54
58
|
};
|
|
55
59
|
|
|
56
60
|
let {
|
|
@@ -85,6 +89,10 @@
|
|
|
85
89
|
hint = undefined, // Add hint destructuring
|
|
86
90
|
selectedValue = $bindable(), // Bindable prop for selected value
|
|
87
91
|
maxSuggestions = undefined, // Maximum number of suggestions to display
|
|
92
|
+
autoselect = true, // Default to false as per library default
|
|
93
|
+
hideHint = false, // Default to false - show hint by default
|
|
94
|
+
prefixMatchOnly = false, // Default to false - show all matches
|
|
95
|
+
autoFocusSubmitOnSelection = false, // Default to false - don't auto-focus by default
|
|
88
96
|
...restSearchProps // Other props for the base Search component
|
|
89
97
|
}: Props = $props();
|
|
90
98
|
|
|
@@ -97,6 +105,8 @@
|
|
|
97
105
|
let currentSourceKey = $state<string | undefined>(undefined);
|
|
98
106
|
let currentSourceProperty = $state<string | undefined>(undefined);
|
|
99
107
|
|
|
108
|
+
|
|
109
|
+
|
|
100
110
|
// --- Derived Values ---
|
|
101
111
|
const wrapperClasses = $derived(
|
|
102
112
|
clsx(
|
|
@@ -254,19 +264,50 @@
|
|
|
254
264
|
populateResults([]);
|
|
255
265
|
return;
|
|
256
266
|
}
|
|
267
|
+
|
|
257
268
|
const lowerQuery = query.toLowerCase();
|
|
258
|
-
const filtered = options.filter((option) => {
|
|
259
|
-
const label = typeof option === "string" ? option : option.label;
|
|
260
|
-
return label.toLowerCase().includes(lowerQuery);
|
|
261
|
-
});
|
|
262
269
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
?
|
|
267
|
-
|
|
270
|
+
if (prefixMatchOnly) {
|
|
271
|
+
// Only show suggestions that start with the query
|
|
272
|
+
const filtered = options.filter((option) => {
|
|
273
|
+
const label = typeof option === "string" ? option : option.label;
|
|
274
|
+
return label.toLowerCase().startsWith(lowerQuery);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Apply maxSuggestions limit if specified
|
|
278
|
+
const limitedResults =
|
|
279
|
+
maxSuggestions && maxSuggestions > 0
|
|
280
|
+
? filtered.slice(0, maxSuggestions)
|
|
281
|
+
: filtered;
|
|
282
|
+
|
|
283
|
+
populateResults(limitedResults);
|
|
284
|
+
} else {
|
|
285
|
+
// Split results into two groups: starts-with and contains (existing behavior)
|
|
286
|
+
const startsWithResults: Suggestion[] = [];
|
|
287
|
+
const containsResults: Suggestion[] = [];
|
|
288
|
+
|
|
289
|
+
options.forEach((option) => {
|
|
290
|
+
const label = typeof option === "string" ? option : option.label;
|
|
291
|
+
const lowerLabel = label.toLowerCase();
|
|
292
|
+
|
|
293
|
+
if (lowerLabel.startsWith(lowerQuery)) {
|
|
294
|
+
startsWithResults.push(option);
|
|
295
|
+
} else if (lowerLabel.includes(lowerQuery)) {
|
|
296
|
+
containsResults.push(option);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Combine results: starts-with first (for better hint behavior), then contains
|
|
301
|
+
const filtered = [...startsWithResults, ...containsResults];
|
|
268
302
|
|
|
269
|
-
|
|
303
|
+
// Apply maxSuggestions limit if specified
|
|
304
|
+
const limitedResults =
|
|
305
|
+
maxSuggestions && maxSuggestions > 0
|
|
306
|
+
? filtered.slice(0, maxSuggestions)
|
|
307
|
+
: filtered;
|
|
308
|
+
|
|
309
|
+
populateResults(limitedResults);
|
|
310
|
+
}
|
|
270
311
|
};
|
|
271
312
|
|
|
272
313
|
// Determine which source to use
|
|
@@ -297,6 +338,7 @@
|
|
|
297
338
|
const dynamicSourceFunction = sourceSelector
|
|
298
339
|
? (query: string, populateResults: (results: Suggestion[]) => void) => {
|
|
299
340
|
const selectedSource = sourceSelector(query, options || []);
|
|
341
|
+
|
|
300
342
|
// Handle invalid returns by falling back to default logic
|
|
301
343
|
if (selectedSource === "api") {
|
|
302
344
|
getResultsFromApi(query, populateResults);
|
|
@@ -366,7 +408,12 @@
|
|
|
366
408
|
// Define confirm function
|
|
367
409
|
let isSubmitting = false; // Prevent double submit
|
|
368
410
|
const handleConfirm = (confirmedValue: Suggestion | undefined) => {
|
|
369
|
-
|
|
411
|
+
console.log('handleConfirm called with:', confirmedValue, 'isSubmitting:', isSubmitting); // Debug log
|
|
412
|
+
|
|
413
|
+
if (confirmedValue === undefined) return;
|
|
414
|
+
|
|
415
|
+
// Reset submitting flag at the start of each new confirmation
|
|
416
|
+
isSubmitting = false;
|
|
370
417
|
|
|
371
418
|
// Re-assign selectedValue before any form-based guard checks (!form) so bindings still update
|
|
372
419
|
// (e.g. when no <form> exists around the component usage) and search component value is being used clienside without a page reload
|
|
@@ -379,23 +426,37 @@
|
|
|
379
426
|
const inputElement =
|
|
380
427
|
autocompleteInstance?.inputElement as HTMLInputElement;
|
|
381
428
|
const form = containerElement?.closest("form");
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
429
|
+
const submitButton = containerElement?.querySelector('button[type="submit"]') as HTMLButtonElement;
|
|
430
|
+
|
|
431
|
+
console.log('Submit button found:', !!submitButton); // Debug log
|
|
432
|
+
|
|
433
|
+
// Always focus the submit button first, regardless of form presence (if feature is enabled)
|
|
434
|
+
if (autoFocusSubmitOnSelection && submitButton) {
|
|
435
|
+
console.log('Focusing submit button'); // Debug log
|
|
436
|
+
// Use requestAnimationFrame to ensure the focus happens after DOM updates
|
|
437
|
+
requestAnimationFrame(() => {
|
|
438
|
+
submitButton.focus();
|
|
439
|
+
console.log('Submit button focused, document.activeElement:', document.activeElement === submitButton);
|
|
440
|
+
});
|
|
394
441
|
}
|
|
395
|
-
|
|
396
|
-
|
|
442
|
+
|
|
443
|
+
// Handle form submission separately
|
|
444
|
+
if (inputElement && form) {
|
|
445
|
+
isSubmitting = true;
|
|
446
|
+
inputElement.value = inputValueTemplate(confirmedValue);
|
|
447
|
+
inputElement.dataset.autocompleteAccepted = "true"; // Set tracking attribute
|
|
448
|
+
|
|
449
|
+
// Submit form immediately
|
|
450
|
+
console.log('Submitting form'); // Debug log
|
|
451
|
+
if (form.requestSubmit) {
|
|
452
|
+
form.requestSubmit();
|
|
453
|
+
} else {
|
|
454
|
+
form.submit(); // Fallback for older browsers
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Reset flag after submission
|
|
397
458
|
isSubmitting = false;
|
|
398
|
-
}
|
|
459
|
+
}
|
|
399
460
|
};
|
|
400
461
|
|
|
401
462
|
// Initialise accessible-autocomplete
|
|
@@ -406,6 +467,8 @@
|
|
|
406
467
|
inputClasses: searchInput.classList, // Pass original classes directly
|
|
407
468
|
source: finalSourceFunction,
|
|
408
469
|
minLength: minLength,
|
|
470
|
+
autoselect: autoselect,
|
|
471
|
+
hintClasses: hideHint ? "hidden-hint" : "",
|
|
409
472
|
confirmOnBlur: confirmOnBlur,
|
|
410
473
|
showNoOptionsFound: showNoOptionsFound,
|
|
411
474
|
defaultValue: defaultValue,
|
|
@@ -430,10 +493,8 @@
|
|
|
430
493
|
const autocompleteInputElement = containerElement?.querySelector(
|
|
431
494
|
".gem-c-search-with-autocomplete__input",
|
|
432
495
|
) as HTMLInputElement | null;
|
|
433
|
-
|
|
434
|
-
//
|
|
435
|
-
// autocompleteInputElement,
|
|
436
|
-
// ); // Updated log
|
|
496
|
+
|
|
497
|
+
// Apply hint visibility classes via hintClasses API
|
|
437
498
|
|
|
438
499
|
// Post-initialisation tweaks
|
|
439
500
|
if (autocompleteInputElement) {
|
|
@@ -446,6 +507,13 @@
|
|
|
446
507
|
// Listen for input changes on the autocomplete field
|
|
447
508
|
autocompleteInputElement.addEventListener("input", () => {
|
|
448
509
|
const val = autocompleteInputElement.value;
|
|
510
|
+
|
|
511
|
+
// Reset isSubmitting flag when user starts typing again
|
|
512
|
+
if (isSubmitting) {
|
|
513
|
+
console.log('User typing, resetting isSubmitting flag');
|
|
514
|
+
isSubmitting = false;
|
|
515
|
+
}
|
|
516
|
+
|
|
449
517
|
// Remove any existing 'too-short' warning before adding a new one to ensure we don't accumulate multiple warning items.
|
|
450
518
|
suggestionsMenu
|
|
451
519
|
?.querySelector(
|
|
@@ -539,6 +607,64 @@
|
|
|
539
607
|
position: relative;
|
|
540
608
|
}
|
|
541
609
|
|
|
610
|
+
/* Hide hint when requested via hintClasses - must come AFTER the default styling for proper cascade */
|
|
611
|
+
.gem-c-search-with-autocomplete
|
|
612
|
+
.gem-c-search-with-autocomplete__hint.hidden-hint {
|
|
613
|
+
display: none !important;
|
|
614
|
+
visibility: hidden !important;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/* Default hint styling when visible - ensure smooth overlapping with main input */
|
|
618
|
+
.gem-c-search-with-autocomplete .gem-c-search-with-autocomplete__hint {
|
|
619
|
+
/* Use identical positioning and sizing as main input */
|
|
620
|
+
position: absolute !important;
|
|
621
|
+
top: 0 !important;
|
|
622
|
+
left: 0 !important;
|
|
623
|
+
z-index: 99 !important;
|
|
624
|
+
|
|
625
|
+
/* Visual styling for hint */
|
|
626
|
+
color: rgba(0, 0, 0, 0.4);
|
|
627
|
+
background: transparent;
|
|
628
|
+
pointer-events: none;
|
|
629
|
+
|
|
630
|
+
/* Copy EXACT styling from main input */
|
|
631
|
+
margin: 0;
|
|
632
|
+
width: 100%;
|
|
633
|
+
height: 2.1052631579em;
|
|
634
|
+
padding: 0.3157894737em;
|
|
635
|
+
border: 2px solid transparent; /* Transparent instead of visible */
|
|
636
|
+
border-radius: 0;
|
|
637
|
+
box-sizing: border-box;
|
|
638
|
+
-webkit-appearance: none;
|
|
639
|
+
-moz-appearance: none;
|
|
640
|
+
appearance: none;
|
|
641
|
+
font-family: "GDS Transport", arial, sans-serif;
|
|
642
|
+
-webkit-font-smoothing: antialiased;
|
|
643
|
+
-moz-osx-font-smoothing: grayscale;
|
|
644
|
+
font-weight: 400;
|
|
645
|
+
font-size: 1.1875rem;
|
|
646
|
+
line-height: 1.4736842105;
|
|
647
|
+
|
|
648
|
+
/* Text alignment */
|
|
649
|
+
text-align: left;
|
|
650
|
+
white-space: nowrap;
|
|
651
|
+
overflow: hidden;
|
|
652
|
+
|
|
653
|
+
/* Ensure visibility - but allow hidden-hint to override */
|
|
654
|
+
display: block;
|
|
655
|
+
visibility: visible;
|
|
656
|
+
opacity: 1;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/* Custom focus styles for submit button (when focused after autocomplete selection) */
|
|
660
|
+
.gem-c-search-with-autocomplete .gem-c-search__submit:focus {
|
|
661
|
+
background-color: #ffdd00; /* GDS focus yellow */
|
|
662
|
+
border-color: #0b0c0c; /* GDS text color for contrast */
|
|
663
|
+
color: #0b0c0c; /* Dark text on yellow background */
|
|
664
|
+
outline: 3px solid #ffdd00;
|
|
665
|
+
outline-offset: 0;
|
|
666
|
+
}
|
|
667
|
+
|
|
542
668
|
.gem-c-search-with-autocomplete__menu {
|
|
543
669
|
margin: 0;
|
|
544
670
|
padding: 0;
|
|
@@ -36,6 +36,10 @@ type Props = {
|
|
|
36
36
|
hint?: string;
|
|
37
37
|
selectedValue?: any;
|
|
38
38
|
maxSuggestions?: number;
|
|
39
|
+
autoselect?: boolean;
|
|
40
|
+
hideHint?: boolean;
|
|
41
|
+
prefixMatchOnly?: boolean;
|
|
42
|
+
autoFocusSubmitOnSelection?: boolean;
|
|
39
43
|
};
|
|
40
44
|
declare const SearchAutocomplete: import("svelte").Component<Props, {}, "selectedValue">;
|
|
41
45
|
type SearchAutocomplete = ReturnType<typeof SearchAutocomplete>;
|