@communitiesuk/svelte-component-library 0.1.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.
- package/README.md +188 -0
- package/dist/assets/css/govuk-frontend.min.css +2 -0
- package/dist/assets/css/govuk-frontend.min.css.map +1 -0
- package/dist/assets/fonts/bold-affa96571d-v2.woff +0 -0
- package/dist/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
- package/dist/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
- package/dist/assets/fonts/light-f591b13f7d-v2.woff +0 -0
- package/dist/assets/govuk_publishing_components/images/icon-autocomplete-search-suggestion.svg +4 -0
- package/dist/assets/govuk_publishing_components/images/icon-close.svg +1 -0
- package/dist/assets/images/favicon.ico +0 -0
- package/dist/assets/images/favicon.svg +1 -0
- package/dist/assets/images/govuk-crest-2x.png +0 -0
- package/dist/assets/images/govuk-crest.png +0 -0
- package/dist/assets/images/govuk-crest.svg +1 -0
- package/dist/assets/images/govuk-icon-180.png +0 -0
- package/dist/assets/images/govuk-icon-192.png +0 -0
- package/dist/assets/images/govuk-icon-512.png +0 -0
- package/dist/assets/images/govuk-icon-mask.svg +1 -0
- package/dist/assets/images/govuk-opengraph-image.png +0 -0
- package/dist/assets/images/homepage-illustration.svg +1 -0
- package/dist/assets/images/homepage.svg +44 -0
- package/dist/assets/images/masthead-illustration.svg +123 -0
- package/dist/assets/images/oflog_crest_black.png +0 -0
- package/dist/assets/images/oflog_crest_white.png +0 -0
- package/dist/assets/images/undraw_approved-wireframe_odf4.svg +1 -0
- package/dist/assets/images/undraw_collaborators_rgw4.svg +1 -0
- package/dist/assets/images/undraw_content-creator_vuqg.svg +1 -0
- package/dist/assets/images/undraw_online-media_opxh.svg +1 -0
- package/dist/assets/images/undraw_pull-request_zlsu.svg +1 -0
- package/dist/assets/images/undraw_reviewed-docs_g0cg.svg +1 -0
- package/dist/components/FilterPanel/codeBlocks.d.ts +3 -0
- package/dist/components/FilterPanel/codeBlocks.js +418 -0
- package/dist/components/content/InsetText.svelte +21 -0
- package/dist/components/content/InsetText.svelte.d.ts +7 -0
- package/dist/components/content/WarningText.svelte +27 -0
- package/dist/components/content/WarningText.svelte.d.ts +8 -0
- package/dist/components/data-vis/axis/Axis.svelte +51 -0
- package/dist/components/data-vis/axis/Axis.svelte.d.ts +33 -0
- package/dist/components/data-vis/axis/Ticks.svelte +113 -0
- package/dist/components/data-vis/axis/Ticks.svelte.d.ts +33 -0
- package/dist/components/data-vis/line-chart/Line.svelte +150 -0
- package/dist/components/data-vis/line-chart/Line.svelte.d.ts +85 -0
- package/dist/components/data-vis/line-chart/LineChart.svelte +249 -0
- package/dist/components/data-vis/line-chart/LineChart.svelte.d.ts +73 -0
- package/dist/components/data-vis/line-chart/Lines.svelte +138 -0
- package/dist/components/data-vis/line-chart/Lines.svelte.d.ts +57 -0
- package/dist/components/data-vis/line-chart/Marker.svelte +61 -0
- package/dist/components/data-vis/line-chart/Marker.svelte.d.ts +37 -0
- package/dist/components/data-vis/line-chart/SeriesLabel.svelte +67 -0
- package/dist/components/data-vis/line-chart/SeriesLabel.svelte.d.ts +43 -0
- package/dist/components/data-vis/line-chart/ValueLabel.svelte +50 -0
- package/dist/components/data-vis/line-chart/ValueLabel.svelte.d.ts +25 -0
- package/dist/components/data-vis/map/Map.svelte +392 -0
- package/dist/components/data-vis/map/Map.svelte.d.ts +47 -0
- package/dist/components/data-vis/map/MapLegend.svelte +41 -0
- package/dist/components/data-vis/map/MapLegend.svelte.d.ts +15 -0
- package/dist/components/data-vis/map/NonStandardControls.svelte +42 -0
- package/dist/components/data-vis/map/NonStandardControls.svelte.d.ts +13 -0
- package/dist/components/data-vis/map/Tooltip.svelte +41 -0
- package/dist/components/data-vis/map/Tooltip.svelte.d.ts +19 -0
- package/dist/components/data-vis/map/colorbrewer.d.ts +337 -0
- package/dist/components/data-vis/map/colorbrewer.js +1523 -0
- package/dist/components/data-vis/map/colors.d.ts +13 -0
- package/dist/components/data-vis/map/colors.js +65 -0
- package/dist/components/data-vis/map/dataJoin.d.ts +2 -0
- package/dist/components/data-vis/map/dataJoin.js +27 -0
- package/dist/components/data-vis/map/fullTopo.json +1 -0
- package/dist/components/data-vis/map/jenks.d.ts +1 -0
- package/dist/components/data-vis/map/jenks.js +51 -0
- package/dist/components/data-vis/map/lad2023.json +1 -0
- package/dist/components/data-vis/map/mapUtils.d.ts +5 -0
- package/dist/components/data-vis/map/mapUtils.js +86 -0
- package/dist/components/data-vis/map/topo.json +1 -0
- package/dist/components/data-vis/table/Table.svelte +247 -0
- package/dist/components/data-vis/table/Table.svelte.d.ts +19 -0
- package/dist/components/layout/Breadcrumbs.svelte +191 -0
- package/dist/components/layout/Breadcrumbs.svelte.d.ts +24 -0
- package/dist/components/layout/Footer.svelte +171 -0
- package/dist/components/layout/Footer.svelte.d.ts +30 -0
- package/dist/components/layout/Header.svelte +43 -0
- package/dist/components/layout/Header.svelte.d.ts +7 -0
- package/dist/components/layout/InternalHeader.svelte +628 -0
- package/dist/components/layout/InternalHeader.svelte.d.ts +15 -0
- package/dist/components/layout/PhaseBanner.svelte +28 -0
- package/dist/components/layout/PhaseBanner.svelte.d.ts +9 -0
- package/dist/components/layout/ServiceNavigation.svelte +143 -0
- package/dist/components/layout/ServiceNavigation.svelte.d.ts +13 -0
- package/dist/components/layout/SideNavigation.svelte +345 -0
- package/dist/components/layout/SideNavigation.svelte.d.ts +25 -0
- package/dist/components/layout/service-navigation-nested-mobile/HeaderNav.svelte +91 -0
- package/dist/components/layout/service-navigation-nested-mobile/HeaderNav.svelte.d.ts +15 -0
- package/dist/components/layout/service-navigation-nested-mobile/MobileNav.svelte +233 -0
- package/dist/components/layout/service-navigation-nested-mobile/MobileNav.svelte.d.ts +27 -0
- package/dist/components/layout/service-navigation-nested-mobile/ServiceNavigationNestedMobile.svelte +70 -0
- package/dist/components/layout/service-navigation-nested-mobile/ServiceNavigationNestedMobile.svelte.d.ts +11 -0
- package/dist/components/layout/service-navigation-nested-mobile/SideNav.svelte +276 -0
- package/dist/components/layout/service-navigation-nested-mobile/SideNav.svelte.d.ts +22 -0
- package/dist/components/ui/Accordion.svelte +244 -0
- package/dist/components/ui/Accordion.svelte.d.ts +23 -0
- package/dist/components/ui/Breadcrumbs.svelte +198 -0
- package/dist/components/ui/Breadcrumbs.svelte.d.ts +24 -0
- package/dist/components/ui/Button.svelte +96 -0
- package/dist/components/ui/Button.svelte.d.ts +17 -0
- package/dist/components/ui/CheckBox.svelte +198 -0
- package/dist/components/ui/CheckBox.svelte.d.ts +27 -0
- package/dist/components/ui/ContentsList.svelte +1117 -0
- package/dist/components/ui/ContentsList.svelte.d.ts +25 -0
- package/dist/components/ui/DateInput.svelte +255 -0
- package/dist/components/ui/DateInput.svelte.d.ts +59 -0
- package/dist/components/ui/Details.svelte +12 -0
- package/dist/components/ui/Details.svelte.d.ts +13 -0
- package/dist/components/ui/FilterPanel.svelte +588 -0
- package/dist/components/ui/FilterPanel.svelte.d.ts +74 -0
- package/dist/components/ui/Footer.svelte +171 -0
- package/dist/components/ui/Footer.svelte.d.ts +30 -0
- package/dist/components/ui/Header.svelte +43 -0
- package/dist/components/ui/Header.svelte.d.ts +7 -0
- package/dist/components/ui/Masthead.svelte +267 -0
- package/dist/components/ui/Masthead.svelte.d.ts +12 -0
- package/dist/components/ui/NavigationExample.svelte +117 -0
- package/dist/components/ui/NavigationExample.svelte.d.ts +3 -0
- package/dist/components/ui/NotificationBanner.svelte +93 -0
- package/dist/components/ui/NotificationBanner.svelte.d.ts +15 -0
- package/dist/components/ui/Radios.svelte +176 -0
- package/dist/components/ui/Radios.svelte.d.ts +28 -0
- package/dist/components/ui/RelatedContent.svelte +596 -0
- package/dist/components/ui/RelatedContent.svelte.d.ts +29 -0
- package/dist/components/ui/Search.svelte +499 -0
- package/dist/components/ui/Search.svelte.d.ts +32 -0
- package/dist/components/ui/SearchAutocomplete.svelte +655 -0
- package/dist/components/ui/SearchAutocomplete.svelte.d.ts +37 -0
- package/dist/components/ui/Select.svelte +116 -0
- package/dist/components/ui/Select.svelte.d.ts +22 -0
- package/dist/components/ui/ServiceNavigation.svelte +143 -0
- package/dist/components/ui/ServiceNavigation.svelte.d.ts +13 -0
- package/dist/components/ui/SideNavigation.svelte +346 -0
- package/dist/components/ui/SideNavigation.svelte.d.ts +25 -0
- package/dist/components/ui/Tabs.svelte +306 -0
- package/dist/components/ui/Tabs.svelte.d.ts +18 -0
- package/dist/components/ui/WhatsNew.svelte +155 -0
- package/dist/components/ui/WhatsNew.svelte.d.ts +29 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.js +44 -0
- package/dist/icons/DoubleChevronButton.svelte +62 -0
- package/dist/icons/DoubleChevronButton.svelte.d.ts +13 -0
- package/dist/icons/IconSearch.svelte +42 -0
- package/dist/icons/IconSearch.svelte.d.ts +6 -0
- package/dist/icons/SingleChevronButtonWithLabel.svelte +132 -0
- package/dist/icons/SingleChevronButtonWithLabel.svelte.d.ts +19 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +45 -0
- package/dist/main.css +1 -0
- package/dist/package-wrapping/BaseInformation.svelte +82 -0
- package/dist/package-wrapping/BaseInformation.svelte.d.ts +15 -0
- package/dist/package-wrapping/BaseNameAndStatus.svelte +108 -0
- package/dist/package-wrapping/BaseNameAndStatus.svelte.d.ts +10 -0
- package/dist/package-wrapping/CodeBlock.svelte +62 -0
- package/dist/package-wrapping/CodeBlock.svelte.d.ts +12 -0
- package/dist/package-wrapping/ComponentDemo.svelte +114 -0
- package/dist/package-wrapping/ComponentDemo.svelte.d.ts +25 -0
- package/dist/package-wrapping/ComponentDemoTEMP.svelte +305 -0
- package/dist/package-wrapping/ComponentDemoTEMP.svelte.d.ts +21 -0
- package/dist/package-wrapping/ComponentDetails.svelte +123 -0
- package/dist/package-wrapping/ComponentDetails.svelte.d.ts +13 -0
- package/dist/package-wrapping/DividerLine.svelte +21 -0
- package/dist/package-wrapping/DividerLine.svelte.d.ts +17 -0
- package/dist/package-wrapping/InputForParameter.svelte +205 -0
- package/dist/package-wrapping/InputForParameter.svelte.d.ts +13 -0
- package/dist/package-wrapping/InputForParameterUpdated.svelte +222 -0
- package/dist/package-wrapping/InputForParameterUpdated.svelte.d.ts +17 -0
- package/dist/package-wrapping/InputForParameterUpdatedTEMP.svelte +203 -0
- package/dist/package-wrapping/InputForParameterUpdatedTEMP.svelte.d.ts +17 -0
- package/dist/package-wrapping/ListOfComponentStatuses.svelte +19 -0
- package/dist/package-wrapping/ListOfComponentStatuses.svelte.d.ts +11 -0
- package/dist/package-wrapping/OverlayAndComponentContainer.svelte +426 -0
- package/dist/package-wrapping/OverlayAndComponentContainer.svelte.d.ts +33 -0
- package/dist/package-wrapping/ParametersSection.svelte +235 -0
- package/dist/package-wrapping/ParametersSection.svelte.d.ts +19 -0
- package/dist/package-wrapping/ParsingErrorToastsContainer.svelte +50 -0
- package/dist/package-wrapping/ParsingErrorToastsContainer.svelte.d.ts +15 -0
- package/dist/package-wrapping/Pill.svelte +54 -0
- package/dist/package-wrapping/Pill.svelte.d.ts +25 -0
- package/dist/package-wrapping/PlaygroundDetails.svelte +106 -0
- package/dist/package-wrapping/PlaygroundDetails.svelte.d.ts +13 -0
- package/dist/package-wrapping/ScreenSizeRadio.svelte +24 -0
- package/dist/package-wrapping/ScreenSizeRadio.svelte.d.ts +11 -0
- package/dist/package-wrapping/ScreenSizeRadioUpdated.svelte +23 -0
- package/dist/package-wrapping/ScreenSizeRadioUpdated.svelte.d.ts +11 -0
- package/dist/package-wrapping/SidebarContainer.svelte +103 -0
- package/dist/package-wrapping/SidebarContainer.svelte.d.ts +23 -0
- package/dist/package-wrapping/WrapperDetailsUpdate.svelte +40 -0
- package/dist/package-wrapping/WrapperDetailsUpdate.svelte.d.ts +15 -0
- package/dist/package-wrapping/templates/Template.svelte +100 -0
- package/dist/package-wrapping/templates/Template.svelte.d.ts +25 -0
- package/dist/templates/ComponentPageTemplate.svelte +1 -0
- package/dist/templates/ComponentPageTemplate.svelte.d.ts +26 -0
- package/dist/utils/data-transformations/convertCSV.d.ts +2 -0
- package/dist/utils/data-transformations/convertCSV.js +22 -0
- package/dist/utils/data-transformations/getValueFromParametersArray.d.ts +1 -0
- package/dist/utils/data-transformations/getValueFromParametersArray.js +9 -0
- package/dist/utils/layoutNavHelpers.d.ts +70 -0
- package/dist/utils/layoutNavHelpers.js +129 -0
- package/dist/utils/package-wrapping-specific/addIndexAndInitialValue.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/addIndexAndInitialValue.js +21 -0
- package/dist/utils/package-wrapping-specific/createBindableParametersValuesArray.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/createBindableParametersValuesArray.js +12 -0
- package/dist/utils/package-wrapping-specific/createParametersObject.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/createParametersObject.js +29 -0
- package/dist/utils/package-wrapping-specific/defineDefaultEventHandler.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/defineDefaultEventHandler.js +14 -0
- package/dist/utils/package-wrapping-specific/trackVisibleParameters.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/trackVisibleParameters.js +29 -0
- package/dist/utils/syntax-highlighting/shikiHighlight.d.ts +7 -0
- package/dist/utils/syntax-highlighting/shikiHighlight.js +76 -0
- package/dist/utils/text-string-conversion/textStringConversion.d.ts +9 -0
- package/dist/utils/text-string-conversion/textStringConversion.js +86 -0
- package/package.json +113 -0
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import Search from "./Search.svelte"; // Base component
|
|
5
|
+
import "accessible-autocomplete/dist/accessible-autocomplete.min.css";
|
|
6
|
+
import { browser } from "$app/environment";
|
|
7
|
+
import suggestionIconUrl from "../../assets/govuk_publishing_components/images/icon-autocomplete-search-suggestion.svg?url";
|
|
8
|
+
import closeIconUrl from "../../assets/govuk_publishing_components/images/icon-close.svg?url"; // Import for the cancel button
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// SSR-safe HTML sanitizer: no-op on server
|
|
12
|
+
let sanitize: (html: string) => string = (html) => html;
|
|
13
|
+
|
|
14
|
+
// --- Define Props ---
|
|
15
|
+
type SuggestionObject = { label: string; value: any };
|
|
16
|
+
type Suggestion = string | SuggestionObject;
|
|
17
|
+
type Props = {
|
|
18
|
+
// User can supply either an options array or an API source
|
|
19
|
+
options?: Suggestion[]; // Predefined suggestions list
|
|
20
|
+
source_url?: string; // Optional: URL for autocomplete suggestions
|
|
21
|
+
source_key?: string; // Optional: Key in the JSON response containing suggestions array
|
|
22
|
+
source_property?: string; // Property to extract from API objects
|
|
23
|
+
outerClasses?: string; // Optional classes for the outer wrapper
|
|
24
|
+
outerDataAttributes?: Record<string, string>; // Optional data attributes for the outer wrapper
|
|
25
|
+
// Add other expected props passed down (e.g., size, on_govuk_blue, id, name etc.)
|
|
26
|
+
size?: "large" | "";
|
|
27
|
+
on_govuk_blue?: boolean;
|
|
28
|
+
homepage?: boolean;
|
|
29
|
+
id?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
label_text?: string;
|
|
32
|
+
button_text?: string;
|
|
33
|
+
// Include any other props you expect to pass through
|
|
34
|
+
[key: string]: any; // Allow other props via rest spread, less type-safe
|
|
35
|
+
// --- Add new props for accessible-autocomplete config ---
|
|
36
|
+
minLength?: number;
|
|
37
|
+
confirmOnBlur?: boolean;
|
|
38
|
+
showNoOptionsFound?: boolean;
|
|
39
|
+
defaultValue?: string;
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
required?: boolean;
|
|
42
|
+
tNoResults?: () => string; // Function prop
|
|
43
|
+
tAssistiveHint?: () => string; // Function prop
|
|
44
|
+
menuAttributes?: Record<string, any>; // Object prop
|
|
45
|
+
menuClasses?: string | null;
|
|
46
|
+
hint?: string; // Add hint prop
|
|
47
|
+
selectedValue?: any; // Bindable selected value, updated on selection
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
let {
|
|
51
|
+
options = undefined,
|
|
52
|
+
source_url = undefined,
|
|
53
|
+
source_key = undefined,
|
|
54
|
+
source_property = undefined,
|
|
55
|
+
size = "", // Default size from Search
|
|
56
|
+
on_govuk_blue = false,
|
|
57
|
+
homepage = false, // Added homepage prop handling
|
|
58
|
+
outerClasses = "",
|
|
59
|
+
outerDataAttributes = {},
|
|
60
|
+
id, // Pass down id
|
|
61
|
+
name = "q", // Pass down name or use default
|
|
62
|
+
label_text = "Search", // Example: Default label
|
|
63
|
+
button_text = "Search", // Pass down button text
|
|
64
|
+
// --- Destructure new props ---
|
|
65
|
+
minLength = 3, // Default from accessible-autocomplete
|
|
66
|
+
confirmOnBlur = false, // Default from accessible-autocomplete
|
|
67
|
+
showNoOptionsFound = true, // Default from accessible-autocomplete
|
|
68
|
+
defaultValue = "", // Default to empty string
|
|
69
|
+
placeholder = "",
|
|
70
|
+
required = false,
|
|
71
|
+
tNoResults = () => "No results found", // Default function
|
|
72
|
+
tAssistiveHint = () =>
|
|
73
|
+
"When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.", // Default function
|
|
74
|
+
menuAttributes = {},
|
|
75
|
+
menuClasses = "", // Default to empty string
|
|
76
|
+
hint = undefined, // Add hint destructuring
|
|
77
|
+
selectedValue = $bindable(), // Bindable prop for selected value
|
|
78
|
+
...restSearchProps // Other props for the base Search component
|
|
79
|
+
}: Props = $props();
|
|
80
|
+
|
|
81
|
+
let containerElement: HTMLDivElement; // bind:this target for the outer div
|
|
82
|
+
let autocompleteInstance: { inputElement?: HTMLInputElement } | null = null; // To store instance if needed
|
|
83
|
+
|
|
84
|
+
// --- Derived Values ---
|
|
85
|
+
const wrapperClasses = $derived(
|
|
86
|
+
clsx(
|
|
87
|
+
"gem-c-search-with-autocomplete",
|
|
88
|
+
size === "large" && "gem-c-search-with-autocomplete--large",
|
|
89
|
+
(on_govuk_blue || homepage) &&
|
|
90
|
+
"gem-c-search-with-autocomplete--on-govuk-blue", // Apply blue style if either is true
|
|
91
|
+
// TODO: Replicate margin logic from Ruby template if needed using govuk utility classes
|
|
92
|
+
outerClasses,
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Prepare props for the inner Search component
|
|
97
|
+
const searchComponentOptions = $derived({
|
|
98
|
+
...restSearchProps,
|
|
99
|
+
label_text, // Pass down explicitly
|
|
100
|
+
button_text, // Pass down explicitly
|
|
101
|
+
id, // Pass id down
|
|
102
|
+
name, // Pass name down
|
|
103
|
+
inline_label: false, // Force separate label for autocomplete compatibility
|
|
104
|
+
size, // Pass size down
|
|
105
|
+
on_govuk_blue, // Pass blue status down
|
|
106
|
+
homepage, // Pass homepage status down
|
|
107
|
+
hint, // Pass the hint prop down
|
|
108
|
+
value: undefined, // Don't pass initial value, let autocomplete handle it
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// custom "too-short" message
|
|
112
|
+
function tooShort(min: number) {
|
|
113
|
+
return `Enter ${min} or more characters for suggestions`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// --- Lifecycle & Autocomplete Initialisation ---
|
|
117
|
+
onMount(async () => {
|
|
118
|
+
// console.log("SearchAutocomplete: onMount started.");
|
|
119
|
+
|
|
120
|
+
if (browser) {
|
|
121
|
+
// hook up DOMPurify sanitize in browser
|
|
122
|
+
const DOMPurify = (await import("dompurify")).default;
|
|
123
|
+
sanitize = DOMPurify.sanitize;
|
|
124
|
+
|
|
125
|
+
// now load autocomplete
|
|
126
|
+
const accessibleAutocomplete = (await import("accessible-autocomplete"))
|
|
127
|
+
.default;
|
|
128
|
+
|
|
129
|
+
// Assert type for querySelector results
|
|
130
|
+
const targetInputWrapper = containerElement?.querySelector(
|
|
131
|
+
".js-search-input-wrapper",
|
|
132
|
+
) as HTMLDivElement | null;
|
|
133
|
+
const searchInput = containerElement?.querySelector(
|
|
134
|
+
'input[type="search"]',
|
|
135
|
+
) as HTMLInputElement | null; // Assert as HTMLInputElement
|
|
136
|
+
|
|
137
|
+
if (!targetInputWrapper || !searchInput) {
|
|
138
|
+
console.error(
|
|
139
|
+
"SearchAutocomplete: Could not find target elements for initialisation.",
|
|
140
|
+
);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// --- Define Source Functions ---
|
|
145
|
+
|
|
146
|
+
// Source function for fetching from API
|
|
147
|
+
const getResultsFromApi = (
|
|
148
|
+
query: string,
|
|
149
|
+
populateResults: (results: string[]) => void,
|
|
150
|
+
) => {
|
|
151
|
+
if (!source_url || !source_key) {
|
|
152
|
+
console.error(
|
|
153
|
+
"SearchAutocomplete: source_url and source_key are required for API mode.",
|
|
154
|
+
);
|
|
155
|
+
populateResults([]);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const url = new URL(source_url);
|
|
159
|
+
url.searchParams.set("q", query);
|
|
160
|
+
fetch(url, { headers: { Accept: "application/json" } })
|
|
161
|
+
.then((response) => {
|
|
162
|
+
if (!response.ok)
|
|
163
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
164
|
+
return response.json();
|
|
165
|
+
})
|
|
166
|
+
.then((data) => {
|
|
167
|
+
// console.log("SearchAutocomplete: Data fetched:", data);
|
|
168
|
+
const results = data[source_key] || [];
|
|
169
|
+
if (!Array.isArray(results)) {
|
|
170
|
+
console.error(
|
|
171
|
+
"SearchAutocomplete: Source key did not return an array.",
|
|
172
|
+
);
|
|
173
|
+
populateResults([]);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// --- API MAPPING LOGIC ---
|
|
177
|
+
populateResults(
|
|
178
|
+
results.map((item: any) => {
|
|
179
|
+
if (typeof item === "string") {
|
|
180
|
+
return item;
|
|
181
|
+
} else if (item && typeof item === "object") {
|
|
182
|
+
// 1. Try the specified source_property if provided
|
|
183
|
+
if (source_property && source_property in item) {
|
|
184
|
+
return String(item[source_property]);
|
|
185
|
+
}
|
|
186
|
+
// 2. Fallback to 'label'
|
|
187
|
+
if ("label" in item) return String(item.label);
|
|
188
|
+
// 3. Fallback to 'postcode' (for backwards compatibility/common case)
|
|
189
|
+
if ("postcode" in item) return String(item.postcode);
|
|
190
|
+
// 4. If none found, stringify the object (might be undesirable)
|
|
191
|
+
console.warn(
|
|
192
|
+
"SearchAutocomplete: Could not find 'label', 'postcode', or specified 'source_property' in object:",
|
|
193
|
+
item,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
// 5. Final fallback: stringify the item
|
|
197
|
+
return String(item ?? ""); // Ensure null/undefined becomes empty string
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
200
|
+
})
|
|
201
|
+
.catch((error) => {
|
|
202
|
+
console.error("SearchAutocomplete: Error fetching results:", error);
|
|
203
|
+
populateResults([]);
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Source function for using provided options array
|
|
208
|
+
const getResultsFromOptions = (
|
|
209
|
+
query: string,
|
|
210
|
+
populateResults: (results: Suggestion[]) => void,
|
|
211
|
+
) => {
|
|
212
|
+
if (!options) {
|
|
213
|
+
populateResults([]);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const lowerQuery = query.toLowerCase();
|
|
217
|
+
const filtered = options.filter((option) => {
|
|
218
|
+
const label = typeof option === "string" ? option : option.label;
|
|
219
|
+
return label.toLowerCase().includes(lowerQuery);
|
|
220
|
+
});
|
|
221
|
+
populateResults(filtered);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Determine which source to use
|
|
225
|
+
const useOptions = Array.isArray(options) && options.length > 0;
|
|
226
|
+
const sourceFunction = useOptions
|
|
227
|
+
? getResultsFromOptions
|
|
228
|
+
: getResultsFromApi;
|
|
229
|
+
|
|
230
|
+
// Define suggestion template function (sanitize and highlight)
|
|
231
|
+
const suggestionTemplate = (result: Suggestion): string => {
|
|
232
|
+
const displayLabel = typeof result === "string" ? result : result.label;
|
|
233
|
+
// Basic sanitization
|
|
234
|
+
const scratch = document.createElement("div");
|
|
235
|
+
scratch.textContent = displayLabel;
|
|
236
|
+
const sanitizedResult = sanitize(scratch.innerHTML);
|
|
237
|
+
|
|
238
|
+
// Get the input value directly from the DOM input created by the library
|
|
239
|
+
const inputElement = containerElement?.querySelector(
|
|
240
|
+
".gem-c-search-with-autocomplete__input",
|
|
241
|
+
) as HTMLInputElement | null; // Find the specific input
|
|
242
|
+
const currentInputValue = inputElement?.value?.toLowerCase() || ""; // Get its value
|
|
243
|
+
|
|
244
|
+
const index = currentInputValue
|
|
245
|
+
? sanitizedResult.toLowerCase().indexOf(currentInputValue)
|
|
246
|
+
: -1;
|
|
247
|
+
let html = sanitizedResult;
|
|
248
|
+
|
|
249
|
+
if (currentInputValue && index !== -1) {
|
|
250
|
+
const before = sanitizedResult.slice(0, index);
|
|
251
|
+
const match = sanitizedResult.slice(
|
|
252
|
+
index,
|
|
253
|
+
index + currentInputValue.length,
|
|
254
|
+
);
|
|
255
|
+
const after = sanitizedResult.slice(index + currentInputValue.length);
|
|
256
|
+
html = `${before}<mark class="gem-c-search-with-autocomplete__suggestion-highlight">${match}</mark>${after}`;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Match the GOV.UK structure
|
|
260
|
+
return `
|
|
261
|
+
<div class="gem-c-search-with-autocomplete__option-wrapper">
|
|
262
|
+
<span class="gem-c-search-with-autocomplete__suggestion-icon"></span>
|
|
263
|
+
<span class="gem-c-search-with-autocomplete__suggestion-text">${html}</span>
|
|
264
|
+
</div>
|
|
265
|
+
`;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Define inputValue template function (handles objects)
|
|
269
|
+
const inputValueTemplate = (result: Suggestion | undefined): string => {
|
|
270
|
+
if (result === undefined) return "";
|
|
271
|
+
// Use label for input value if it's an object, otherwise use the string
|
|
272
|
+
return typeof result === "string" ? result : result.label;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// Define confirm function
|
|
276
|
+
let isSubmitting = false; // Prevent double submit
|
|
277
|
+
const handleConfirm = (confirmedValue: Suggestion | undefined) => {
|
|
278
|
+
if (confirmedValue === undefined || isSubmitting) return;
|
|
279
|
+
|
|
280
|
+
// Re-assign selectedValue before any form-based guard checks (!form) so bindings still update
|
|
281
|
+
// (e.g. when no <form> exists around the component usage) and search component value is being used clienside without a page reload
|
|
282
|
+
selectedValue =
|
|
283
|
+
typeof confirmedValue === "string"
|
|
284
|
+
? confirmedValue
|
|
285
|
+
: confirmedValue.value;
|
|
286
|
+
|
|
287
|
+
// Type assertion needed here
|
|
288
|
+
const inputElement =
|
|
289
|
+
autocompleteInstance?.inputElement as HTMLInputElement;
|
|
290
|
+
const form = containerElement?.closest("form");
|
|
291
|
+
|
|
292
|
+
if (!inputElement || !form) return;
|
|
293
|
+
|
|
294
|
+
isSubmitting = true;
|
|
295
|
+
inputElement.value = inputValueTemplate(confirmedValue);
|
|
296
|
+
inputElement.dataset.autocompleteAccepted = "true"; // Set tracking attribute
|
|
297
|
+
|
|
298
|
+
// Submit form
|
|
299
|
+
if (form.requestSubmit) {
|
|
300
|
+
form.requestSubmit();
|
|
301
|
+
} else {
|
|
302
|
+
form.submit(); // Fallback for older browsers
|
|
303
|
+
}
|
|
304
|
+
// Reset flag after a short delay in case submission fails/is prevented
|
|
305
|
+
setTimeout(() => {
|
|
306
|
+
isSubmitting = false;
|
|
307
|
+
}, 500);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
// Initialise accessible-autocomplete
|
|
311
|
+
autocompleteInstance = accessibleAutocomplete({
|
|
312
|
+
element: targetInputWrapper, // Target the div *containing* the input
|
|
313
|
+
id: searchInput.id, // Use the ID from the *rendered* Search input
|
|
314
|
+
name: searchInput.name, // Use the name from the *rendered* Search input
|
|
315
|
+
inputClasses: searchInput.classList, // Pass original classes directly
|
|
316
|
+
source: sourceFunction,
|
|
317
|
+
minLength: minLength,
|
|
318
|
+
confirmOnBlur: confirmOnBlur,
|
|
319
|
+
showNoOptionsFound: showNoOptionsFound,
|
|
320
|
+
defaultValue: defaultValue,
|
|
321
|
+
placeholder: placeholder,
|
|
322
|
+
required: required,
|
|
323
|
+
tNoResults: tNoResults,
|
|
324
|
+
tAssistiveHint: tAssistiveHint,
|
|
325
|
+
menuAttributes: menuAttributes,
|
|
326
|
+
menuClasses: menuClasses,
|
|
327
|
+
tStatusQueryTooShort: tooShort,
|
|
328
|
+
displayMenu: "overlay",
|
|
329
|
+
cssNamespace: "gem-c-search-with-autocomplete",
|
|
330
|
+
onConfirm: handleConfirm,
|
|
331
|
+
templates: {
|
|
332
|
+
suggestion: suggestionTemplate,
|
|
333
|
+
inputValue: inputValueTemplate, // optional template to transform displayed value
|
|
334
|
+
// noOptionsFound: optional template
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Query the DOM for the input element *created* by the library
|
|
339
|
+
const autocompleteInputElement = containerElement?.querySelector(
|
|
340
|
+
".gem-c-search-with-autocomplete__input",
|
|
341
|
+
) as HTMLInputElement | null;
|
|
342
|
+
// console.log(
|
|
343
|
+
// "SearchAutocomplete: Input element queried from DOM:",
|
|
344
|
+
// autocompleteInputElement,
|
|
345
|
+
// ); // Updated log
|
|
346
|
+
|
|
347
|
+
// Post-initialisation tweaks
|
|
348
|
+
if (autocompleteInputElement) {
|
|
349
|
+
// Post-init: dynamically show a 'too-short' warning when the user types fewer than minLength characters
|
|
350
|
+
// Find the dropdown menu <ul> generated by accessible-autocomplete
|
|
351
|
+
const suggestionsMenu =
|
|
352
|
+
containerElement.querySelector<HTMLUListElement>(
|
|
353
|
+
".gem-c-search-with-autocomplete__menu",
|
|
354
|
+
);
|
|
355
|
+
// Listen for input changes on the autocomplete field
|
|
356
|
+
autocompleteInputElement.addEventListener("input", () => {
|
|
357
|
+
const val = autocompleteInputElement.value;
|
|
358
|
+
// Remove any existing 'too-short' warning before adding a new one to ensure we don't accumulate multiple warning items.
|
|
359
|
+
suggestionsMenu
|
|
360
|
+
?.querySelector(
|
|
361
|
+
".gem-c-search-with-autocomplete__option--too-short",
|
|
362
|
+
)
|
|
363
|
+
?.remove();
|
|
364
|
+
if (val.length < minLength) {
|
|
365
|
+
// Force the menu open so the warning is shown
|
|
366
|
+
autocompleteInputElement.setAttribute("aria-expanded", "true");
|
|
367
|
+
suggestionsMenu?.classList.add(
|
|
368
|
+
"gem-c-search-with-autocomplete__menu--visible",
|
|
369
|
+
);
|
|
370
|
+
suggestionsMenu?.classList.remove(
|
|
371
|
+
"gem-c-search-with-autocomplete__menu--hidden",
|
|
372
|
+
);
|
|
373
|
+
// Create a new <li> element with the warning text. Classes match the library's own suggestion items (so it looks and behaves consistently). Set role="option" and aria-disabled="true" for accessibility
|
|
374
|
+
const li = document.createElement("li");
|
|
375
|
+
li.className =
|
|
376
|
+
"gem-c-search-with-autocomplete__option gem-c-search-with-autocomplete__option--too-short";
|
|
377
|
+
li.setAttribute("role", "option");
|
|
378
|
+
li.setAttribute("aria-disabled", "true");
|
|
379
|
+
li.textContent = tooShort(minLength);
|
|
380
|
+
// Insert the warning at the top of the suggestions list menu
|
|
381
|
+
suggestionsMenu?.prepend(li);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
autocompleteInputElement.setAttribute("type", "search"); // Ensure input type is search
|
|
385
|
+
// autocompleteInputElement.classList.add("autocomplete__input"); // Add specific class if needed
|
|
386
|
+
|
|
387
|
+
// Add Enter key workaround from original JS
|
|
388
|
+
autocompleteInputElement.addEventListener("keydown", (e) => {
|
|
389
|
+
if (isSubmitting) return; // Don't interfere if already submitting
|
|
390
|
+
const dropdownVisible =
|
|
391
|
+
autocompleteInputElement.getAttribute("aria-expanded") === "true";
|
|
392
|
+
if (dropdownVisible && e.key === "Enter") {
|
|
393
|
+
const form = containerElement?.closest("form");
|
|
394
|
+
if (form) {
|
|
395
|
+
isSubmitting = true;
|
|
396
|
+
if (form.requestSubmit) form.requestSubmit();
|
|
397
|
+
else form.submit();
|
|
398
|
+
setTimeout(() => {
|
|
399
|
+
isSubmitting = false;
|
|
400
|
+
}, 500);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// console.log(
|
|
406
|
+
// "Autocomplete input classes AFTER add:",
|
|
407
|
+
// Array.from(autocompleteInputElement.classList),
|
|
408
|
+
// );
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// IMPORTANT: Remove the original Search.svelte input, as accessible-autocomplete replaces it.
|
|
412
|
+
// We render it initially so accessible-autocomplete can grab its id, name, value.
|
|
413
|
+
if (searchInput) {
|
|
414
|
+
searchInput.remove(); // Use remove() instead of hiding
|
|
415
|
+
}
|
|
416
|
+
// Also remove the original label if it's still present inside targetInputWrapper
|
|
417
|
+
const originalLabel = targetInputWrapper.querySelector(
|
|
418
|
+
"label",
|
|
419
|
+
) as HTMLLabelElement | null;
|
|
420
|
+
if (originalLabel) {
|
|
421
|
+
originalLabel.remove(); // Use remove() instead of hiding
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}); // End of onMount
|
|
425
|
+
</script>
|
|
426
|
+
|
|
427
|
+
<div
|
|
428
|
+
bind:this={containerElement}
|
|
429
|
+
class={wrapperClasses}
|
|
430
|
+
data-module="gem-search-with-autocomplete"
|
|
431
|
+
data-source-url={source_url}
|
|
432
|
+
data-source-key={source_key}
|
|
433
|
+
data-source-property={source_property}
|
|
434
|
+
{...outerDataAttributes}
|
|
435
|
+
style={`--suggestion-icon: url("${suggestionIconUrl}"); --cancel-icon: url("${closeIconUrl}")`}
|
|
436
|
+
>
|
|
437
|
+
<!-- Render the base Search component initially -->
|
|
438
|
+
<!-- accessible-autocomplete will enhance the input inside it -->
|
|
439
|
+
<Search {...searchComponentOptions} />
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<style>
|
|
443
|
+
/* global to prevent css namespace conflict with original library*/
|
|
444
|
+
:global {
|
|
445
|
+
.gem-c-search-with-autocomplete__wrapper {
|
|
446
|
+
position: relative;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.gem-c-search-with-autocomplete__menu {
|
|
450
|
+
margin: 0;
|
|
451
|
+
padding: 0;
|
|
452
|
+
overflow-x: hidden;
|
|
453
|
+
background-color: #fff;
|
|
454
|
+
border: 1px solid #b1b4b6;
|
|
455
|
+
border-top: 0;
|
|
456
|
+
margin-right: -40px;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.gem-c-search-with-autocomplete__menu--visible {
|
|
460
|
+
display: block;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.gem-c-search-with-autocomplete__menu--hidden {
|
|
464
|
+
display: none;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.gem-c-search-with-autocomplete__menu--inline {
|
|
468
|
+
position: relative;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.gem-c-search-with-autocomplete__option {
|
|
472
|
+
display: block;
|
|
473
|
+
cursor: pointer;
|
|
474
|
+
font-family: "GDS Transport", arial, sans-serif;
|
|
475
|
+
-webkit-font-smoothing: antialiased;
|
|
476
|
+
-moz-osx-font-smoothing: grayscale;
|
|
477
|
+
font-weight: 400;
|
|
478
|
+
font-size: 1.1875rem;
|
|
479
|
+
line-height: 1.3157894737;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@media print {
|
|
483
|
+
.gem-c-search-with-autocomplete__option {
|
|
484
|
+
font-family: sans-serif;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
@media print {
|
|
489
|
+
.gem-c-search-with-autocomplete__option {
|
|
490
|
+
font-size: 14pt;
|
|
491
|
+
line-height: 1.15;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
.gem-c-search-with-autocomplete__option > * {
|
|
496
|
+
pointer-events: none;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
.gem-c-search-with-autocomplete__option > span {
|
|
500
|
+
clip: rect(0 0 0 0);
|
|
501
|
+
clip-path: inset(50%);
|
|
502
|
+
height: 1px;
|
|
503
|
+
overflow: hidden;
|
|
504
|
+
position: absolute;
|
|
505
|
+
white-space: nowrap;
|
|
506
|
+
width: 1px;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.gem-c-search-with-autocomplete__option--focused,
|
|
510
|
+
.gem-c-search-with-autocomplete__option:hover,
|
|
511
|
+
.gem-c-search-with-autocomplete__option:focus-visible {
|
|
512
|
+
background-color: #f3f2f1;
|
|
513
|
+
outline: none;
|
|
514
|
+
text-decoration: underline;
|
|
515
|
+
text-decoration-thickness: max(1px, 0.0625rem);
|
|
516
|
+
text-underline-offset: 0.1578em;
|
|
517
|
+
text-decoration-thickness: max(3px, 0.1875rem, 0.12em);
|
|
518
|
+
-webkit-text-decoration-skip-ink: none;
|
|
519
|
+
text-decoration-skip-ink: none;
|
|
520
|
+
-webkit-text-decoration-skip: none;
|
|
521
|
+
text-decoration-skip: none;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.gem-c-search-with-autocomplete__option--focused
|
|
525
|
+
.gem-c-search-with-autocomplete__suggestion-icon,
|
|
526
|
+
.gem-c-search-with-autocomplete__option:hover
|
|
527
|
+
.gem-c-search-with-autocomplete__suggestion-icon,
|
|
528
|
+
.gem-c-search-with-autocomplete__option:focus-visible
|
|
529
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
|
530
|
+
background-color: #0b0c0c;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.gem-c-search-with-autocomplete__option:focus-visible
|
|
534
|
+
.gem-c-search-with-autocomplete__suggestion-text {
|
|
535
|
+
background-color: #fd0;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.gem-c-search-with-autocomplete__option-wrapper {
|
|
539
|
+
display: flex;
|
|
540
|
+
align-items: center;
|
|
541
|
+
margin: 0 15px;
|
|
542
|
+
padding: 5px 0;
|
|
543
|
+
border-bottom: 1px solid #b1b4b6;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.gem-c-search-with-autocomplete__option:last-child
|
|
547
|
+
.gem-c-search-with-autocomplete__option-wrapper {
|
|
548
|
+
border-bottom: 0;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
|
552
|
+
width: 20px;
|
|
553
|
+
height: 40px;
|
|
554
|
+
margin-right: 10px;
|
|
555
|
+
flex: none;
|
|
556
|
+
mask-image: var(--suggestion-icon);
|
|
557
|
+
-webkit-mask-image: var(--suggestion-icon);
|
|
558
|
+
background-color: #505a5f;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.gem-c-search-with-autocomplete__suggestion-text {
|
|
562
|
+
font-weight: bold;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
|
566
|
+
font-weight: normal;
|
|
567
|
+
background: none;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.gem-c-search-with-autocomplete.gem-c-search-with-autocomplete--large
|
|
571
|
+
.gem-c-search-with-autocomplete__menu {
|
|
572
|
+
margin-right: -50px;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.gem-c-search-with-autocomplete.gem-c-search-with-autocomplete--large
|
|
576
|
+
.gem-c-search-with-autocomplete__option {
|
|
577
|
+
min-height: 50px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.gem-c-search-with-autocomplete.gem-c-search-with-autocomplete--on-govuk-blue
|
|
581
|
+
.gem-c-search-with-autocomplete__menu {
|
|
582
|
+
border-top: 1px solid #b1b4b6;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
@media (forced-colors: active) {
|
|
586
|
+
.gem-c-search-with-autocomplete__menu {
|
|
587
|
+
border-color: FieldText;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.gem-c-search-with-autocomplete__option {
|
|
591
|
+
forced-color-adjust: none;
|
|
592
|
+
background-color: Field;
|
|
593
|
+
color: FieldText;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.gem-c-search-with-autocomplete__option--focused,
|
|
597
|
+
.gem-c-search-with-autocomplete__option:hover,
|
|
598
|
+
.gem-c-search-with-autocomplete__option:focus-visible {
|
|
599
|
+
background-color: Highlight;
|
|
600
|
+
color: HighlightText;
|
|
601
|
+
border-color: FieldText;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.gem-c-search-with-autocomplete__option--focused
|
|
605
|
+
.gem-c-search-with-autocomplete__suggestion-text,
|
|
606
|
+
.gem-c-search-with-autocomplete__option:hover
|
|
607
|
+
.gem-c-search-with-autocomplete__suggestion-text,
|
|
608
|
+
.gem-c-search-with-autocomplete__option:focus-visible
|
|
609
|
+
.gem-c-search-with-autocomplete__suggestion-text {
|
|
610
|
+
background: none;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.gem-c-search-with-autocomplete__option--focused
|
|
614
|
+
.gem-c-search-with-autocomplete__suggestion-highlight,
|
|
615
|
+
.gem-c-search-with-autocomplete__option:hover
|
|
616
|
+
.gem-c-search-with-autocomplete__suggestion-highlight,
|
|
617
|
+
.gem-c-search-with-autocomplete__option:focus-visible
|
|
618
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
|
619
|
+
color: HighlightText;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.gem-c-search-with-autocomplete__option--focused
|
|
623
|
+
.gem-c-search-with-autocomplete__suggestion-icon,
|
|
624
|
+
.gem-c-search-with-autocomplete__option:hover
|
|
625
|
+
.gem-c-search-with-autocomplete__suggestion-icon,
|
|
626
|
+
.gem-c-search-with-autocomplete__option:focus-visible
|
|
627
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
|
628
|
+
background-color: HighlightText;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.gem-c-search-with-autocomplete__option:focus-visible:not(:hover) {
|
|
632
|
+
background-color: SelectedItem;
|
|
633
|
+
color: SelectedItemText;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.gem-c-search-with-autocomplete__option:focus-visible:not(:hover)
|
|
637
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
|
638
|
+
color: SelectedItemText;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.gem-c-search-with-autocomplete__option:focus-visible:not(:hover)
|
|
642
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
|
643
|
+
background-color: SelectedItemText;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
|
647
|
+
color: FieldText;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
|
651
|
+
background-color: FieldText;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
</style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import "accessible-autocomplete/dist/accessible-autocomplete.min.css";
|
|
2
|
+
type SuggestionObject = {
|
|
3
|
+
label: string;
|
|
4
|
+
value: any;
|
|
5
|
+
};
|
|
6
|
+
type Suggestion = string | SuggestionObject;
|
|
7
|
+
type Props = {
|
|
8
|
+
options?: Suggestion[];
|
|
9
|
+
source_url?: string;
|
|
10
|
+
source_key?: string;
|
|
11
|
+
source_property?: string;
|
|
12
|
+
outerClasses?: string;
|
|
13
|
+
outerDataAttributes?: Record<string, string>;
|
|
14
|
+
size?: "large" | "";
|
|
15
|
+
on_govuk_blue?: boolean;
|
|
16
|
+
homepage?: boolean;
|
|
17
|
+
id?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
label_text?: string;
|
|
20
|
+
button_text?: string;
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
minLength?: number;
|
|
23
|
+
confirmOnBlur?: boolean;
|
|
24
|
+
showNoOptionsFound?: boolean;
|
|
25
|
+
defaultValue?: string;
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
tNoResults?: () => string;
|
|
29
|
+
tAssistiveHint?: () => string;
|
|
30
|
+
menuAttributes?: Record<string, any>;
|
|
31
|
+
menuClasses?: string | null;
|
|
32
|
+
hint?: string;
|
|
33
|
+
selectedValue?: any;
|
|
34
|
+
};
|
|
35
|
+
declare const SearchAutocomplete: import("svelte").Component<Props, {}, "selectedValue">;
|
|
36
|
+
type SearchAutocomplete = ReturnType<typeof SearchAutocomplete>;
|
|
37
|
+
export default SearchAutocomplete;
|