entasis 0.13.4 → 0.13.6
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/Address/Address.svelte +44 -0
- package/dist/components/Address/Address.svelte.d.ts +4 -0
- package/dist/components/Address/address.d.ts +99 -0
- package/dist/components/Address/address.google.d.ts +89 -0
- package/dist/components/Address/address.google.fixtures.json +808 -0
- package/dist/components/Address/address.google.js +184 -0
- package/dist/components/Address/address.js +109 -0
- package/dist/components/Address/address.mcp.d.ts +1 -0
- package/dist/components/Address/address.mcp.js +100 -0
- package/dist/components/Address/address.props.d.ts +26 -0
- package/dist/components/Address/address.props.js +1 -0
- package/dist/components/Address/address.provider.d.ts +19 -0
- package/dist/components/Address/address.provider.js +69 -0
- package/dist/components/Address/address.theme.d.ts +63 -0
- package/dist/components/Address/address.theme.js +42 -0
- package/dist/components/Address/index.d.ts +6 -0
- package/dist/components/Address/index.js +5 -0
- package/dist/components/Code/Code.svelte +7 -2
- package/dist/components/Code/CodeTheme.svelte +12 -1
- package/dist/components/Code/code.highlighter.js +2 -2
- package/dist/components/Code/code.mcp.d.ts +1 -1
- package/dist/components/Code/code.mcp.js +3 -1
- package/dist/components/Code/code.theme.js +6 -5
- package/dist/components/Form/AddressInput/AddressInput.svelte +482 -0
- package/dist/components/Form/AddressInput/AddressInput.svelte.d.ts +4 -0
- package/dist/components/Form/AddressInput/addressInput.mcp.d.ts +1 -0
- package/dist/components/Form/AddressInput/addressInput.mcp.js +110 -0
- package/dist/components/Form/AddressInput/addressInput.props.d.ts +72 -0
- package/dist/components/Form/AddressInput/addressInput.props.js +1 -0
- package/dist/components/Form/AddressInput/addressInput.theme.d.ts +63 -0
- package/dist/components/Form/AddressInput/addressInput.theme.js +55 -0
- package/dist/components/Form/AddressInput/index.d.ts +3 -0
- package/dist/components/Form/AddressInput/index.js +2 -0
- package/dist/components/Form/Field/field.d.ts +5 -2
- package/dist/components/Form/Field/field.state.svelte.js +4 -0
- package/dist/components/Form/Field/index.d.ts +1 -1
- package/dist/components/Form/Field/schemas.js +8 -0
- package/dist/components/Form/Form/FormInputRenderer.svelte +6 -0
- package/dist/components/Form/Form/form.d.ts +6 -0
- package/dist/components/Form/Form/form.mcp.d.ts +1 -1
- package/dist/components/Form/Form/form.mcp.js +1 -1
- package/dist/components/Form/Form/form.state.svelte.d.ts +142 -11
- package/dist/components/Form/Form/form.state.svelte.js +2 -0
- package/dist/components/Form/Form/visibility.d.ts +186 -20
- package/dist/components/Form/MultiStepForm/multiStepForm.state.svelte.d.ts +136 -0
- package/dist/components/Form/SignatureInput/SignatureInput.svelte +327 -0
- package/dist/components/Form/SignatureInput/SignatureInput.svelte.d.ts +4 -0
- package/dist/components/Form/SignatureInput/index.d.ts +4 -0
- package/dist/components/Form/SignatureInput/index.js +2 -0
- package/dist/components/Form/SignatureInput/signatureInput.mcp.d.ts +1 -0
- package/dist/components/Form/SignatureInput/signatureInput.mcp.js +74 -0
- package/dist/components/Form/SignatureInput/signatureInput.props.d.ts +29 -0
- package/dist/components/Form/SignatureInput/signatureInput.props.js +1 -0
- package/dist/components/Form/SignatureInput/signatureInput.strokes.d.ts +77 -0
- package/dist/components/Form/SignatureInput/signatureInput.strokes.js +149 -0
- package/dist/components/Form/SignatureInput/signatureInput.theme.d.ts +99 -0
- package/dist/components/Form/SignatureInput/signatureInput.theme.js +70 -0
- package/dist/components/Sidebar/sidebar-layout.js +3 -1
- package/dist/components/Timeline/Timeline.svelte +1 -1
- package/dist/components/Timeline/TimelineEntry.svelte +16 -2
- package/dist/components/Timeline/index.d.ts +1 -1
- package/dist/components/Timeline/timeline.items.d.ts +1 -1
- package/dist/components/Timeline/timeline.items.js +7 -2
- package/dist/components/Timeline/timeline.mcp.d.ts +1 -1
- package/dist/components/Timeline/timeline.mcp.js +35 -3
- package/dist/components/Timeline/timeline.props.d.ts +17 -1
- package/dist/components/Timeline/timeline.theme.d.ts +36 -0
- package/dist/components/Timeline/timeline.theme.js +27 -4
- package/dist/generated/componentAliases.d.ts +3 -0
- package/dist/generated/componentAliases.js +3 -0
- package/dist/generated/componentContract.d.ts +47 -2
- package/dist/generated/componentContract.js +114 -0
- package/dist/generated/componentMcpRegistry.js +6 -0
- package/dist/i18n/ar.js +18 -0
- package/dist/i18n/de.js +18 -0
- package/dist/i18n/en.d.ts +18 -0
- package/dist/i18n/en.js +18 -0
- package/dist/i18n/es.js +18 -0
- package/dist/i18n/fr.js +18 -0
- package/dist/i18n/ja.js +18 -0
- package/dist/i18n/pt.js +18 -0
- package/dist/i18n/zh.js +18 -0
- package/package.json +25 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { composeStreetLine } from './address.js';
|
|
2
|
+
const DEFAULT_ENDPOINT = 'https://places.googleapis.com/v1';
|
|
3
|
+
const DETAILS_FIELD_MASK = 'id,formattedAddress,addressComponents,location';
|
|
4
|
+
const ADDRESS_TYPES = ['street_address', 'premise', 'subpremise', 'route'];
|
|
5
|
+
/** The first component of `place` carrying one of `types`, in the order of `types`. */
|
|
6
|
+
const component = (place, ...types) => {
|
|
7
|
+
for (const type of types) {
|
|
8
|
+
const found = place.addressComponents?.find((entry) => entry.types?.includes(type));
|
|
9
|
+
if (found)
|
|
10
|
+
return found;
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* An `Address` from a Google Place: the street line in the country's order, the postal town
|
|
16
|
+
* or the nearest locality as the city, the first administrative level as the region (its short
|
|
17
|
+
* form in the United States, Canada and Australia, where it is written "CA" or "NSW").
|
|
18
|
+
*/
|
|
19
|
+
export function parseGooglePlace(place) {
|
|
20
|
+
const countryCode = component(place, 'country')?.shortText?.toUpperCase() ?? null;
|
|
21
|
+
const streetNumber = component(place, 'street_number')?.longText ?? null;
|
|
22
|
+
const street = component(place, 'route')?.longText ?? null;
|
|
23
|
+
const region = component(place, 'administrative_area_level_1');
|
|
24
|
+
const shortRegion = countryCode === 'US' || countryCode === 'CA' || countryCode === 'AU';
|
|
25
|
+
const premise = component(place, 'subpremise', 'premise')?.longText ?? null;
|
|
26
|
+
const latitude = place.location?.latitude;
|
|
27
|
+
const longitude = place.location?.longitude;
|
|
28
|
+
return {
|
|
29
|
+
line1: composeStreetLine(streetNumber, street, countryCode) ?? premise,
|
|
30
|
+
line2: composeStreetLine(streetNumber, street, countryCode) ? premise : null,
|
|
31
|
+
postalCode: component(place, 'postal_code')?.longText ?? null,
|
|
32
|
+
city: component(place, 'locality', 'postal_town', 'sublocality_level_1', 'sublocality', 'administrative_area_level_3', 'administrative_area_level_2')?.longText ?? null,
|
|
33
|
+
region: (shortRegion ? region?.shortText : region?.longText) ?? null,
|
|
34
|
+
country: component(place, 'country')?.longText ?? null,
|
|
35
|
+
countryCode,
|
|
36
|
+
streetNumber,
|
|
37
|
+
street,
|
|
38
|
+
formatted: place.formattedAddress ?? null,
|
|
39
|
+
placeId: place.id ?? null,
|
|
40
|
+
location: typeof latitude === 'number' && typeof longitude === 'number'
|
|
41
|
+
? { lat: latitude, lng: longitude }
|
|
42
|
+
: null
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** A Places request that failed, with its HTTP status. */
|
|
46
|
+
export class GooglePlacesError extends Error {
|
|
47
|
+
status;
|
|
48
|
+
constructor(status, message) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.status = status;
|
|
51
|
+
this.name = 'GooglePlacesError';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function failure(response) {
|
|
55
|
+
let message = `Google Places request failed (${response.status})`;
|
|
56
|
+
try {
|
|
57
|
+
const body = (await response.json());
|
|
58
|
+
if (body.error?.message)
|
|
59
|
+
message = `Google Places: ${body.error.message}`;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Not JSON: keep the status.
|
|
63
|
+
}
|
|
64
|
+
return new GooglePlacesError(response.status, message);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* An `AddressProvider` backed by Google Places (Places API "New"). Pass a browser `apiKey`, or an
|
|
68
|
+
* `endpoint` on your server that adds the key, so it never reaches the page.
|
|
69
|
+
*/
|
|
70
|
+
export function createGooglePlacesProvider(options = {}) {
|
|
71
|
+
const endpoint = (options.endpoint ?? DEFAULT_ENDPOINT).replace(/\/$/, '');
|
|
72
|
+
const types = options.types ?? ADDRESS_TYPES;
|
|
73
|
+
const request = (input, init) => {
|
|
74
|
+
const headers = new Headers(init.headers);
|
|
75
|
+
if (options.apiKey)
|
|
76
|
+
headers.set('X-Goog-Api-Key', options.apiKey);
|
|
77
|
+
return (options.fetch ?? fetch)(`${endpoint}${input}`, { ...init, headers });
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
async search(query, { signal, session, language, countries }) {
|
|
81
|
+
const input = query.trim();
|
|
82
|
+
if (!input)
|
|
83
|
+
return [];
|
|
84
|
+
const response = await request('/places:autocomplete', {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
signal,
|
|
87
|
+
headers: { 'Content-Type': 'application/json' },
|
|
88
|
+
body: JSON.stringify({
|
|
89
|
+
input,
|
|
90
|
+
sessionToken: session,
|
|
91
|
+
languageCode: language ?? options.language,
|
|
92
|
+
regionCode: options.region,
|
|
93
|
+
includedRegionCodes: countries?.length
|
|
94
|
+
? countries.map((code) => code.toLowerCase())
|
|
95
|
+
: undefined,
|
|
96
|
+
includedPrimaryTypes: types.length ? types : undefined
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok)
|
|
100
|
+
throw await failure(response);
|
|
101
|
+
const body = (await response.json());
|
|
102
|
+
return (body.suggestions ?? []).flatMap((suggestion) => {
|
|
103
|
+
const prediction = suggestion.placePrediction;
|
|
104
|
+
if (!prediction?.placeId)
|
|
105
|
+
return [];
|
|
106
|
+
const main = prediction.structuredFormat?.mainText?.text;
|
|
107
|
+
return [
|
|
108
|
+
{
|
|
109
|
+
id: prediction.placeId,
|
|
110
|
+
label: main ?? prediction.text?.text ?? '',
|
|
111
|
+
description: main ? prediction.structuredFormat?.secondaryText?.text : undefined
|
|
112
|
+
}
|
|
113
|
+
];
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
async resolve(id, { signal, session, language }) {
|
|
117
|
+
const params = new URLSearchParams({ sessionToken: session });
|
|
118
|
+
const languageCode = language ?? options.language;
|
|
119
|
+
if (languageCode)
|
|
120
|
+
params.set('languageCode', languageCode);
|
|
121
|
+
if (options.region)
|
|
122
|
+
params.set('regionCode', options.region);
|
|
123
|
+
const response = await request(`/places/${encodeURIComponent(id)}?${params}`, {
|
|
124
|
+
method: 'GET',
|
|
125
|
+
signal,
|
|
126
|
+
headers: { 'X-Goog-FieldMask': DETAILS_FIELD_MASK }
|
|
127
|
+
});
|
|
128
|
+
if (!response.ok)
|
|
129
|
+
throw await failure(response);
|
|
130
|
+
return parseGooglePlace((await response.json()));
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const AUTOCOMPLETE_PATH = /\/places:autocomplete$/;
|
|
135
|
+
const PLACE_PATH = /\/places\/([\w-]+)$/;
|
|
136
|
+
/**
|
|
137
|
+
* Server handlers for the route `AddressInput` searches through by default
|
|
138
|
+
* (`/api/places/[...path]`): they forward the two Places calls to Google with the server's key.
|
|
139
|
+
* Nothing else passes: any other path or method answers 404, so the route is not an open proxy.
|
|
140
|
+
*
|
|
141
|
+
* ```ts
|
|
142
|
+
* // src/routes/api/places/[...path]/+server.ts
|
|
143
|
+
* import { createGooglePlacesProxy } from './index.ts';
|
|
144
|
+
* export const { GET, POST } = createGooglePlacesProxy({ apiKey: GOOGLE_PLACE_API_KEY });
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export function createGooglePlacesProxy({ apiKey, fetch: fetchImpl }) {
|
|
148
|
+
const notFound = () => new Response('Not found', { status: 404 });
|
|
149
|
+
const forward = async (path, init, search = '') => {
|
|
150
|
+
if (!apiKey)
|
|
151
|
+
return notFound();
|
|
152
|
+
const headers = new Headers(init.headers);
|
|
153
|
+
headers.set('X-Goog-Api-Key', apiKey);
|
|
154
|
+
const response = await (fetchImpl ?? fetch)(`${DEFAULT_ENDPOINT}${path}${search}`, {
|
|
155
|
+
...init,
|
|
156
|
+
headers
|
|
157
|
+
});
|
|
158
|
+
return new Response(response.body, {
|
|
159
|
+
status: response.status,
|
|
160
|
+
headers: { 'Content-Type': response.headers.get('Content-Type') ?? 'application/json' }
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
return {
|
|
164
|
+
POST: async ({ request }) => {
|
|
165
|
+
if (!AUTOCOMPLETE_PATH.test(new URL(request.url).pathname))
|
|
166
|
+
return notFound();
|
|
167
|
+
return forward('/places:autocomplete', {
|
|
168
|
+
method: 'POST',
|
|
169
|
+
headers: { 'Content-Type': 'application/json' },
|
|
170
|
+
body: await request.text()
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
GET: async ({ request }) => {
|
|
174
|
+
const url = new URL(request.url);
|
|
175
|
+
const id = PLACE_PATH.exec(url.pathname)?.[1];
|
|
176
|
+
if (!id)
|
|
177
|
+
return notFound();
|
|
178
|
+
return forward(`/places/${id}`, {
|
|
179
|
+
method: 'GET',
|
|
180
|
+
headers: { 'X-Goog-FieldMask': DETAILS_FIELD_MASK }
|
|
181
|
+
}, url.search);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A postal address as entasis stores, edits and displays it, the order its lines take in each
|
|
3
|
+
* country, and the provider contract an address search plugs into.
|
|
4
|
+
*/
|
|
5
|
+
/** Every address part, in the order a form usually asks for them. */
|
|
6
|
+
export const ADDRESS_FIELDS = [
|
|
7
|
+
'line1',
|
|
8
|
+
'line2',
|
|
9
|
+
'postalCode',
|
|
10
|
+
'city',
|
|
11
|
+
'region',
|
|
12
|
+
'country'
|
|
13
|
+
];
|
|
14
|
+
const text = (value) => (value ?? '').trim();
|
|
15
|
+
/** True when no part a person reads (lines, postal code, city, region, country) is filled. */
|
|
16
|
+
export function isAddressEmpty(address) {
|
|
17
|
+
if (!address)
|
|
18
|
+
return true;
|
|
19
|
+
return ADDRESS_FIELDS.every((field) => text(address[field]) === '');
|
|
20
|
+
}
|
|
21
|
+
// Countries that write the street number after the street name ("Hauptstraße 12").
|
|
22
|
+
const NUMBER_AFTER_STREET = new Set([
|
|
23
|
+
'AR', 'AT', 'BA', 'BE', 'BG', 'BO', 'BR', 'CH', 'CL', 'CO', 'CR', 'CZ', 'DE', 'DK', 'EE', 'ES',
|
|
24
|
+
'FI', 'GR', 'HR', 'HU', 'IS', 'IT', 'LI', 'LT', 'LV', 'MX', 'NL', 'NO', 'PE', 'PL', 'PT', 'RO',
|
|
25
|
+
'RS', 'SE', 'SI', 'SK', 'TR', 'UY', 'VE'
|
|
26
|
+
]); // prettier-ignore
|
|
27
|
+
/** The street line for a number and a street, in the order `countryCode` writes them. */
|
|
28
|
+
export function composeStreetLine(streetNumber, street, countryCode) {
|
|
29
|
+
const number = text(streetNumber);
|
|
30
|
+
const name = text(street);
|
|
31
|
+
if (!number || !name)
|
|
32
|
+
return name || number || null;
|
|
33
|
+
return NUMBER_AFTER_STREET.has((countryCode ?? '').toUpperCase())
|
|
34
|
+
? `${name} ${number}`
|
|
35
|
+
: `${number} ${name}`;
|
|
36
|
+
}
|
|
37
|
+
// Countries whose locality line reads "City, REGION POSTAL" (North America, Australia).
|
|
38
|
+
const CITY_REGION_POSTAL = new Set(['US', 'CA', 'AU', 'PR', 'GU', 'VI', 'AS', 'MP']);
|
|
39
|
+
// Countries that put the postal code on its own line after the city (UK and Ireland).
|
|
40
|
+
const POSTAL_OWN_LINE = new Set(['GB', 'IE', 'IM', 'JE', 'GG']);
|
|
41
|
+
/** The country name for `address`: its own `country`, or `countryCode` written in `locale`. */
|
|
42
|
+
export function addressCountryName(address, locale) {
|
|
43
|
+
const name = text(address.country);
|
|
44
|
+
if (name)
|
|
45
|
+
return name;
|
|
46
|
+
const code = text(address.countryCode).toUpperCase();
|
|
47
|
+
return code ? countryName(code, locale) : '';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The lines of an address as the country writes them: street lines, then the locality line
|
|
51
|
+
* (postal code and city, in the country's order, with the region where it belongs), then the
|
|
52
|
+
* country. Empty parts and empty lines are left out.
|
|
53
|
+
*/
|
|
54
|
+
export function formatAddress(address, { fields = ADDRESS_FIELDS, locale } = {}) {
|
|
55
|
+
if (!address)
|
|
56
|
+
return [];
|
|
57
|
+
const has = new Set(fields);
|
|
58
|
+
const part = (field) => (has.has(field) ? text(address[field]) : '');
|
|
59
|
+
const code = text(address.countryCode).toUpperCase();
|
|
60
|
+
const postal = part('postalCode');
|
|
61
|
+
const city = part('city');
|
|
62
|
+
const region = part('region');
|
|
63
|
+
const lines = [part('line1'), part('line2')];
|
|
64
|
+
if (CITY_REGION_POSTAL.has(code)) {
|
|
65
|
+
const regionPostal = [region, postal].filter(Boolean).join(' ');
|
|
66
|
+
lines.push([city, regionPostal].filter(Boolean).join(', '));
|
|
67
|
+
}
|
|
68
|
+
else if (POSTAL_OWN_LINE.has(code)) {
|
|
69
|
+
lines.push(city, region, postal);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
lines.push([postal, city].filter(Boolean).join(' '), region);
|
|
73
|
+
}
|
|
74
|
+
if (has.has('country'))
|
|
75
|
+
lines.push(addressCountryName(address, locale));
|
|
76
|
+
return lines.filter(Boolean);
|
|
77
|
+
}
|
|
78
|
+
/** The address on one line, its lines joined by ", ". */
|
|
79
|
+
export const formatAddressLine = (address, options) => formatAddress(address, options).join(', ');
|
|
80
|
+
/** ISO 3166-1 alpha-2 codes of every country and territory a postal address can be in. */
|
|
81
|
+
export const COUNTRY_CODES = ('AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR ' +
|
|
82
|
+
'BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ ' +
|
|
83
|
+
'EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW ' +
|
|
84
|
+
'GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY ' +
|
|
85
|
+
'KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV ' +
|
|
86
|
+
'MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY ' +
|
|
87
|
+
'QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG ' +
|
|
88
|
+
'TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS XK YE YT ZA ' +
|
|
89
|
+
'ZM ZW').split(' ');
|
|
90
|
+
const displayNames = new Map();
|
|
91
|
+
/** The name of the country `code` in `locale`, or the code itself when Intl cannot name it. */
|
|
92
|
+
export function countryName(code, locale) {
|
|
93
|
+
const key = locale ?? '';
|
|
94
|
+
if (!displayNames.has(key)) {
|
|
95
|
+
try {
|
|
96
|
+
displayNames.set(key, new Intl.DisplayNames(locale ? [locale] : undefined, { type: 'region' }));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
displayNames.set(key, null);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const upper = code.toUpperCase();
|
|
103
|
+
try {
|
|
104
|
+
return displayNames.get(key)?.of(upper) ?? upper;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return upper;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const addressDescription = "\n# Address\n\n`entasis/address` holds the address model, the line order of each country, an `<Address>` display component, and the Google Places search `AddressInput` uses by default (with the server route that serves it).\n\n## Display\n\n```svelte\n<script lang=\"ts\">\n import { Address, type AddressValue } from './index.ts';\n\n const office: AddressValue = {\n line1: '12 Rue de Rivoli',\n postalCode: '75004',\n city: 'Paris',\n countryCode: 'FR'\n };\n</script>\n\n<Address address={office} />\n<Address address={office} layout=\"inline\" fields={['line1', 'city']} />\n```\n\nProps:\n\n- **address**: `AddressValue | null` \u2014 the address to display.\n- **fields**: `AddressField[]` \u2014 parts to show (`line1`, `line2`, `postalCode`, `city`, `region`, `country`). Defaults to every part. The order on screen follows the country, not this list.\n- **layout**: `'block' | 'inline'` (default `'block'`) \u2014 one line per row, or every line joined by \", \".\n- **size**: `'small' | 'normal' | 'large'` \u2014 text size.\n- **empty**: `string | Snippet` \u2014 shown when nothing is left to display.\n- **ref**, **class**, **theme** (parts `root`, `line`, `empty`), and native attributes of the root `<address>`.\n\n## The address value\n\n```ts\ntype AddressValue = {\n line1?: string | null; // \"12 Rue de Rivoli\", \"Friedrichstra\u00DFe 43\"\n line2?: string | null; // apartment, suite, building\n postalCode?: string | null;\n city?: string | null;\n region?: string | null; // state, province (\"CA\" in the US, Canada and Australia)\n country?: string | null; // country name\n countryCode?: string | null; // ISO 3166-1 alpha-2, decides the line order\n streetNumber?: string | null;\n street?: string | null;\n formatted?: string | null; // the provider's one-line address\n placeId?: string | null;\n location?: { lat: number; lng: number } | null;\n};\n```\n\n`streetNumber`, `street`, `formatted`, `placeId` and `location` come from a provider and are cleared by a manual edit that no longer matches them.\n\n## Formatting\n\n- `formatAddress(value, { fields?, locale? })` returns the lines in the country's order: street lines, then \"75004 Paris\" in most of Europe and Latin America, \"Mountain View, CA 94043\" in the US, Canada and Australia, the city and the postcode on their own lines in the UK and Ireland, then the country (named in `locale` when only `countryCode` is set).\n- `formatAddressLine(value, options)` joins them with \", \".\n- `composeStreetLine(number, street, countryCode)` writes the number before the street, or after it in Germany, the Netherlands, Italy, Spain, Scandinavia, Latin America and the rest of continental Europe.\n- `isAddressEmpty(value)`, `countryName(code, locale)`, `addressCountryName(value, locale)`, `COUNTRY_CODES`, `ADDRESS_FIELDS`.\n\n## Providers\n\nAn `AddressProvider` is two functions: `search(query, request)` returns `{ id, label, description? }` suggestions, and `resolve(id, request)` returns the full address. `request` carries `signal`, a `session` id shared by the searches and the resolve of one chosen address, `language` and `countries`.\n\n### Google Places, built in\n\nAddressInput searches Google Places by itself, through the app's `/api/places` route. That route is the whole setup:\n\n```ts nocheck\n// src/routes/api/places/[...path]/+server.ts\nimport { createGooglePlacesProxy } from 'entasis/address';\nimport { GOOGLE_PLACE_API_KEY } from '$app/env/private';\n\nexport const { GET, POST } = createGooglePlacesProxy({ apiKey: GOOGLE_PLACE_API_KEY });\n```\n\n- `createGooglePlacesProxy({ apiKey, fetch? })` returns `GET` and `POST` request handlers (`({ request }) => Response`, so SvelteKit and any Fetch-API server take them). They forward exactly two calls to Places API (New) with the server's key: `POST \u2026/places:autocomplete` and `GET \u2026/places/{id}` (field mask `id,formattedAddress,addressComponents,location`). Anything else, or a missing key, answers 404: the route is not an open proxy, and the key never reaches the page. Restrict the key to Places API (New) in the Google Cloud console.\n- Without the route (it answers 404), the search turns itself off for the page and the parts are typed by hand; the dev server warns once.\n- `DEFAULT_ADDRESS_ENDPOINT` is `'/api/places'`.\n\n### Another provider, or none\n\n- `setAddressProvider(provider)` in a layout sets the search for every AddressInput below, such as `createGooglePlacesProvider({ apiKey: PUBLIC_KEY })` to call Google from the browser with a key restricted to your sites, or a provider for another service. `setAddressProvider(null)` turns the search off.\n- An AddressInput's own `provider` prop wins over both; `provider={null}` turns its search off.\n\n### createGooglePlacesProvider\n\n```ts\nimport { createGooglePlacesProvider } from 'entasis/address';\n\nconst fromBrowser = createGooglePlacesProvider({ apiKey: PUBLIC_GOOGLE_PLACES_KEY });\nconst throughAnotherRoute = createGooglePlacesProvider({ endpoint: '/geo/places' });\n```\n\n- Uses Places API (New) over REST: `POST {endpoint}/places:autocomplete` and `GET {endpoint}/places/{id}`. No Google SDK is loaded.\n- Options: `apiKey`, `endpoint` (default `https://places.googleapis.com/v1`), `language`, `region`, `types` (default `street_address`, `premise`, `subpremise`, `route`, so shops and landmarks stay out; `[]` for every place), `fetch`.\n- The session token groups the autocomplete calls and the details call, so Google bills one session per chosen address.\n- `parseGooglePlace(place)` turns a Place's `addressComponents` into an `AddressValue`: the street line in the country's order, `locality` (or `postal_town`, then the nearest sublocality or administrative level) as the city, the first administrative level as the region, and `location` as `{ lat, lng }`.\n- A failed request rejects with a `GooglePlacesError` carrying Google's message and the HTTP `status`; AddressInput shows the search as failed and keeps the parts editable.\n";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const addressDescription = `
|
|
2
|
+
# Address
|
|
3
|
+
|
|
4
|
+
\`entasis/address\` holds the address model, the line order of each country, an \`<Address>\` display component, and the Google Places search \`AddressInput\` uses by default (with the server route that serves it).
|
|
5
|
+
|
|
6
|
+
## Display
|
|
7
|
+
|
|
8
|
+
\`\`\`svelte
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import { Address, type AddressValue } from './index.ts';
|
|
11
|
+
|
|
12
|
+
const office: AddressValue = {
|
|
13
|
+
line1: '12 Rue de Rivoli',
|
|
14
|
+
postalCode: '75004',
|
|
15
|
+
city: 'Paris',
|
|
16
|
+
countryCode: 'FR'
|
|
17
|
+
};
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Address address={office} />
|
|
21
|
+
<Address address={office} layout="inline" fields={['line1', 'city']} />
|
|
22
|
+
\`\`\`
|
|
23
|
+
|
|
24
|
+
Props:
|
|
25
|
+
|
|
26
|
+
- **address**: \`AddressValue | null\` — the address to display.
|
|
27
|
+
- **fields**: \`AddressField[]\` — parts to show (\`line1\`, \`line2\`, \`postalCode\`, \`city\`, \`region\`, \`country\`). Defaults to every part. The order on screen follows the country, not this list.
|
|
28
|
+
- **layout**: \`'block' | 'inline'\` (default \`'block'\`) — one line per row, or every line joined by ", ".
|
|
29
|
+
- **size**: \`'small' | 'normal' | 'large'\` — text size.
|
|
30
|
+
- **empty**: \`string | Snippet\` — shown when nothing is left to display.
|
|
31
|
+
- **ref**, **class**, **theme** (parts \`root\`, \`line\`, \`empty\`), and native attributes of the root \`<address>\`.
|
|
32
|
+
|
|
33
|
+
## The address value
|
|
34
|
+
|
|
35
|
+
\`\`\`ts
|
|
36
|
+
type AddressValue = {
|
|
37
|
+
line1?: string | null; // "12 Rue de Rivoli", "Friedrichstraße 43"
|
|
38
|
+
line2?: string | null; // apartment, suite, building
|
|
39
|
+
postalCode?: string | null;
|
|
40
|
+
city?: string | null;
|
|
41
|
+
region?: string | null; // state, province ("CA" in the US, Canada and Australia)
|
|
42
|
+
country?: string | null; // country name
|
|
43
|
+
countryCode?: string | null; // ISO 3166-1 alpha-2, decides the line order
|
|
44
|
+
streetNumber?: string | null;
|
|
45
|
+
street?: string | null;
|
|
46
|
+
formatted?: string | null; // the provider's one-line address
|
|
47
|
+
placeId?: string | null;
|
|
48
|
+
location?: { lat: number; lng: number } | null;
|
|
49
|
+
};
|
|
50
|
+
\`\`\`
|
|
51
|
+
|
|
52
|
+
\`streetNumber\`, \`street\`, \`formatted\`, \`placeId\` and \`location\` come from a provider and are cleared by a manual edit that no longer matches them.
|
|
53
|
+
|
|
54
|
+
## Formatting
|
|
55
|
+
|
|
56
|
+
- \`formatAddress(value, { fields?, locale? })\` returns the lines in the country's order: street lines, then "75004 Paris" in most of Europe and Latin America, "Mountain View, CA 94043" in the US, Canada and Australia, the city and the postcode on their own lines in the UK and Ireland, then the country (named in \`locale\` when only \`countryCode\` is set).
|
|
57
|
+
- \`formatAddressLine(value, options)\` joins them with ", ".
|
|
58
|
+
- \`composeStreetLine(number, street, countryCode)\` writes the number before the street, or after it in Germany, the Netherlands, Italy, Spain, Scandinavia, Latin America and the rest of continental Europe.
|
|
59
|
+
- \`isAddressEmpty(value)\`, \`countryName(code, locale)\`, \`addressCountryName(value, locale)\`, \`COUNTRY_CODES\`, \`ADDRESS_FIELDS\`.
|
|
60
|
+
|
|
61
|
+
## Providers
|
|
62
|
+
|
|
63
|
+
An \`AddressProvider\` is two functions: \`search(query, request)\` returns \`{ id, label, description? }\` suggestions, and \`resolve(id, request)\` returns the full address. \`request\` carries \`signal\`, a \`session\` id shared by the searches and the resolve of one chosen address, \`language\` and \`countries\`.
|
|
64
|
+
|
|
65
|
+
### Google Places, built in
|
|
66
|
+
|
|
67
|
+
AddressInput searches Google Places by itself, through the app's \`/api/places\` route. That route is the whole setup:
|
|
68
|
+
|
|
69
|
+
\`\`\`ts nocheck
|
|
70
|
+
// src/routes/api/places/[...path]/+server.ts
|
|
71
|
+
import { createGooglePlacesProxy } from './index.ts';
|
|
72
|
+
import { GOOGLE_PLACE_API_KEY } from '$app/env/private';
|
|
73
|
+
|
|
74
|
+
export const { GET, POST } = createGooglePlacesProxy({ apiKey: GOOGLE_PLACE_API_KEY });
|
|
75
|
+
\`\`\`
|
|
76
|
+
|
|
77
|
+
- \`createGooglePlacesProxy({ apiKey, fetch? })\` returns \`GET\` and \`POST\` request handlers (\`({ request }) => Response\`, so SvelteKit and any Fetch-API server take them). They forward exactly two calls to Places API (New) with the server's key: \`POST …/places:autocomplete\` and \`GET …/places/{id}\` (field mask \`id,formattedAddress,addressComponents,location\`). Anything else, or a missing key, answers 404: the route is not an open proxy, and the key never reaches the page. Restrict the key to Places API (New) in the Google Cloud console.
|
|
78
|
+
- Without the route (it answers 404), the search turns itself off for the page and the parts are typed by hand; the dev server warns once.
|
|
79
|
+
- \`DEFAULT_ADDRESS_ENDPOINT\` is \`'/api/places'\`.
|
|
80
|
+
|
|
81
|
+
### Another provider, or none
|
|
82
|
+
|
|
83
|
+
- \`setAddressProvider(provider)\` in a layout sets the search for every AddressInput below, such as \`createGooglePlacesProvider({ apiKey: PUBLIC_KEY })\` to call Google from the browser with a key restricted to your sites, or a provider for another service. \`setAddressProvider(null)\` turns the search off.
|
|
84
|
+
- An AddressInput's own \`provider\` prop wins over both; \`provider={null}\` turns its search off.
|
|
85
|
+
|
|
86
|
+
### createGooglePlacesProvider
|
|
87
|
+
|
|
88
|
+
\`\`\`ts
|
|
89
|
+
import { createGooglePlacesProvider } from './index.ts';
|
|
90
|
+
|
|
91
|
+
const fromBrowser = createGooglePlacesProvider({ apiKey: PUBLIC_GOOGLE_PLACES_KEY });
|
|
92
|
+
const throughAnotherRoute = createGooglePlacesProvider({ endpoint: '/geo/places' });
|
|
93
|
+
\`\`\`
|
|
94
|
+
|
|
95
|
+
- Uses Places API (New) over REST: \`POST {endpoint}/places:autocomplete\` and \`GET {endpoint}/places/{id}\`. No Google SDK is loaded.
|
|
96
|
+
- Options: \`apiKey\`, \`endpoint\` (default \`https://places.googleapis.com/v1\`), \`language\`, \`region\`, \`types\` (default \`street_address\`, \`premise\`, \`subpremise\`, \`route\`, so shops and landmarks stay out; \`[]\` for every place), \`fetch\`.
|
|
97
|
+
- The session token groups the autocomplete calls and the details call, so Google bills one session per chosen address.
|
|
98
|
+
- \`parseGooglePlace(place)\` turns a Place's \`addressComponents\` into an \`AddressValue\`: the street line in the country's order, \`locality\` (or \`postal_town\`, then the nearest sublocality or administrative level) as the city, the first administrative level as the region, and \`location\` as \`{ lat, lng }\`.
|
|
99
|
+
- A failed request rejects with a \`GooglePlacesError\` carrying Google's message and the HTTP \`status\`; AddressInput shows the search as failed and keeps the parts editable.
|
|
100
|
+
`;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Slot } from '../Slot/slot.js';
|
|
2
|
+
import type { WithAttachments } from '../../types/props.js';
|
|
3
|
+
import type { Sizes } from '../../types/theme.js';
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
import type { Address as AddressValue, AddressField } from './address.js';
|
|
6
|
+
import type { AddressThemeProps } from './address.theme.js';
|
|
7
|
+
/** `block` writes one line per row; `inline` joins the lines with ", " on one line. */
|
|
8
|
+
export type AddressLayout = 'block' | 'inline';
|
|
9
|
+
export type AddressProps = WithAttachments<Omit<HTMLAttributes<HTMLElement>, 'class' | 'children'> & {
|
|
10
|
+
/** The address to display. */
|
|
11
|
+
address: AddressValue | null | undefined;
|
|
12
|
+
/** Parts to display. Defaults to every part. Their order follows the country, not this list. */
|
|
13
|
+
fields?: readonly AddressField[];
|
|
14
|
+
/** One line per row, or every line on one. */
|
|
15
|
+
layout?: AddressLayout;
|
|
16
|
+
/** Text size. */
|
|
17
|
+
size?: Sizes;
|
|
18
|
+
/** Shown when the address has nothing to display. Defaults to nothing. */
|
|
19
|
+
empty?: Slot;
|
|
20
|
+
/** Bindable reference to the root `<address>`. */
|
|
21
|
+
ref?: HTMLElement | null;
|
|
22
|
+
/** Additional classes for the root `<address>`. */
|
|
23
|
+
class?: string;
|
|
24
|
+
/** Per-instance theme overrides. */
|
|
25
|
+
theme?: AddressThemeProps;
|
|
26
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AddressProvider } from './address.js';
|
|
2
|
+
/** The route the built-in provider searches through. */
|
|
3
|
+
export declare const DEFAULT_ADDRESS_ENDPOINT = "/api/places";
|
|
4
|
+
/**
|
|
5
|
+
* Sets the address search every AddressInput below uses, unless it is given its own `provider`.
|
|
6
|
+
* Call it in a layout, such as with `createGooglePlacesProvider({ apiKey })` for a browser key or
|
|
7
|
+
* another endpoint. Pass `null` to turn the search off.
|
|
8
|
+
*/
|
|
9
|
+
export declare function setAddressProvider(provider: AddressProvider | null): void;
|
|
10
|
+
/** The provider set with `setAddressProvider` above this component, if any. */
|
|
11
|
+
export declare function getAddressProvider(): {
|
|
12
|
+
provider: AddressProvider | null;
|
|
13
|
+
} | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Google Places through `/api/places`. When the app has no such route (it answers 404), the
|
|
16
|
+
* search turns itself off for the page: the fields stay, typed by hand, and the dev server says
|
|
17
|
+
* once how to add the route.
|
|
18
|
+
*/
|
|
19
|
+
export declare function builtInAddressProvider(): AddressProvider;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The address search a field uses when it is given none: Google Places through the app's own
|
|
3
|
+
* `/api/places` route (see `createGooglePlacesProxy`), or the provider set for the subtree.
|
|
4
|
+
*/
|
|
5
|
+
import { DEV } from 'esm-env';
|
|
6
|
+
import { getContext, setContext } from 'svelte';
|
|
7
|
+
import { createGooglePlacesProvider, GooglePlacesError } from './address.google.js';
|
|
8
|
+
/** The route the built-in provider searches through. */
|
|
9
|
+
export const DEFAULT_ADDRESS_ENDPOINT = '/api/places';
|
|
10
|
+
const CONTEXT = Symbol('entasis.addressProvider');
|
|
11
|
+
/**
|
|
12
|
+
* Sets the address search every AddressInput below uses, unless it is given its own `provider`.
|
|
13
|
+
* Call it in a layout, such as with `createGooglePlacesProvider({ apiKey })` for a browser key or
|
|
14
|
+
* another endpoint. Pass `null` to turn the search off.
|
|
15
|
+
*/
|
|
16
|
+
export function setAddressProvider(provider) {
|
|
17
|
+
setContext(CONTEXT, { provider });
|
|
18
|
+
}
|
|
19
|
+
/** The provider set with `setAddressProvider` above this component, if any. */
|
|
20
|
+
export function getAddressProvider() {
|
|
21
|
+
return getContext(CONTEXT);
|
|
22
|
+
}
|
|
23
|
+
let builtIn;
|
|
24
|
+
/**
|
|
25
|
+
* Google Places through `/api/places`. When the app has no such route (it answers 404), the
|
|
26
|
+
* search turns itself off for the page: the fields stay, typed by hand, and the dev server says
|
|
27
|
+
* once how to add the route.
|
|
28
|
+
*/
|
|
29
|
+
export function builtInAddressProvider() {
|
|
30
|
+
if (builtIn)
|
|
31
|
+
return builtIn;
|
|
32
|
+
const google = createGooglePlacesProvider({ endpoint: DEFAULT_ADDRESS_ENDPOINT });
|
|
33
|
+
let available = true;
|
|
34
|
+
const missing = (error) => {
|
|
35
|
+
if (!(error instanceof GooglePlacesError) || error.status !== 404)
|
|
36
|
+
return false;
|
|
37
|
+
available = false;
|
|
38
|
+
if (DEV)
|
|
39
|
+
console.warn(`entasis: AddressInput searches Google Places through ${DEFAULT_ADDRESS_ENDPOINT}, which this app does not serve. Add src/routes/api/places/[...path]/+server.ts with \`export const { GET, POST } = createGooglePlacesProxy({ apiKey })\` from 'entasis/address', or pass a \`provider\`.`);
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
builtIn = {
|
|
43
|
+
async search(query, request) {
|
|
44
|
+
if (!available)
|
|
45
|
+
return [];
|
|
46
|
+
try {
|
|
47
|
+
return await google.search(query, request);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (missing(error))
|
|
51
|
+
return [];
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
async resolve(id, request) {
|
|
56
|
+
if (!available)
|
|
57
|
+
return null;
|
|
58
|
+
try {
|
|
59
|
+
return await google.resolve(id, request);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (missing(error))
|
|
63
|
+
return null;
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return builtIn;
|
|
69
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type InferComponentTheme } from '../../utils/cva/index.js';
|
|
2
|
+
export declare const addressTheme: {
|
|
3
|
+
root: (props?: (import("../../utils/cva/types.ts").CVAVariantSchema<{
|
|
4
|
+
size: {
|
|
5
|
+
small: string;
|
|
6
|
+
normal: string;
|
|
7
|
+
large: string;
|
|
8
|
+
};
|
|
9
|
+
layout: {
|
|
10
|
+
block: string;
|
|
11
|
+
inline: string;
|
|
12
|
+
};
|
|
13
|
+
}> & import("../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
14
|
+
line: (props?: (import("../../utils/cva/types.ts").CVAVariantSchema<{
|
|
15
|
+
layout: {
|
|
16
|
+
block: string;
|
|
17
|
+
inline: string;
|
|
18
|
+
};
|
|
19
|
+
}> & import("../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
20
|
+
empty: (props?: import("../../utils/cva/types.ts").CVAClassProp | undefined) => string;
|
|
21
|
+
};
|
|
22
|
+
export type AddressTheme = typeof addressTheme;
|
|
23
|
+
export type AddressThemeProps = InferComponentTheme<AddressTheme>;
|
|
24
|
+
export declare const setAddressTheme: (theme: InferComponentTheme<{
|
|
25
|
+
root: (props?: (import("../../utils/cva/types.ts").CVAVariantSchema<{
|
|
26
|
+
size: {
|
|
27
|
+
small: string;
|
|
28
|
+
normal: string;
|
|
29
|
+
large: string;
|
|
30
|
+
};
|
|
31
|
+
layout: {
|
|
32
|
+
block: string;
|
|
33
|
+
inline: string;
|
|
34
|
+
};
|
|
35
|
+
}> & import("../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
36
|
+
line: (props?: (import("../../utils/cva/types.ts").CVAVariantSchema<{
|
|
37
|
+
layout: {
|
|
38
|
+
block: string;
|
|
39
|
+
inline: string;
|
|
40
|
+
};
|
|
41
|
+
}> & import("../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
42
|
+
empty: (props?: import("../../utils/cva/types.ts").CVAClassProp | undefined) => string;
|
|
43
|
+
}>) => void;
|
|
44
|
+
export declare const useAddressTheme: import("../../utils/cva/theme.ts").UseComponentTheme<{
|
|
45
|
+
root: (props?: (import("../../utils/cva/types.ts").CVAVariantSchema<{
|
|
46
|
+
size: {
|
|
47
|
+
small: string;
|
|
48
|
+
normal: string;
|
|
49
|
+
large: string;
|
|
50
|
+
};
|
|
51
|
+
layout: {
|
|
52
|
+
block: string;
|
|
53
|
+
inline: string;
|
|
54
|
+
};
|
|
55
|
+
}> & import("../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
56
|
+
line: (props?: (import("../../utils/cva/types.ts").CVAVariantSchema<{
|
|
57
|
+
layout: {
|
|
58
|
+
block: string;
|
|
59
|
+
inline: string;
|
|
60
|
+
};
|
|
61
|
+
}> & import("../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
62
|
+
empty: (props?: import("../../utils/cva/types.ts").CVAClassProp | undefined) => string;
|
|
63
|
+
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { cva, setComponentTheme, useComponentTheme } from '../../utils/cva/index.js';
|
|
2
|
+
// An <address> resets the browser's italic: it reads as plain text in the surrounding type.
|
|
3
|
+
const defaultRoot = cva({
|
|
4
|
+
base: 'min-w-0 text-neutral not-italic',
|
|
5
|
+
variants: {
|
|
6
|
+
size: {
|
|
7
|
+
small: 'text-xs',
|
|
8
|
+
normal: 'text-sm',
|
|
9
|
+
large: 'text-base'
|
|
10
|
+
},
|
|
11
|
+
layout: {
|
|
12
|
+
block: 'flex flex-col',
|
|
13
|
+
inline: 'inline'
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
size: 'normal',
|
|
18
|
+
layout: 'block'
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const defaultLine = cva({
|
|
22
|
+
base: 'min-w-0',
|
|
23
|
+
variants: {
|
|
24
|
+
layout: {
|
|
25
|
+
block: 'block',
|
|
26
|
+
inline: 'inline'
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
layout: 'block'
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const defaultEmpty = cva({
|
|
34
|
+
base: 'text-neutral/70'
|
|
35
|
+
});
|
|
36
|
+
export const addressTheme = {
|
|
37
|
+
root: defaultRoot,
|
|
38
|
+
line: defaultLine,
|
|
39
|
+
empty: defaultEmpty
|
|
40
|
+
};
|
|
41
|
+
export const setAddressTheme = setComponentTheme('address');
|
|
42
|
+
export const useAddressTheme = useComponentTheme('address', addressTheme);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as Address } from './Address.svelte';
|
|
2
|
+
export type { AddressLayout, AddressProps } from './address.props.js';
|
|
3
|
+
export { ADDRESS_FIELDS, COUNTRY_CODES, addressCountryName, composeStreetLine, countryName, formatAddress, formatAddressLine, isAddressEmpty, type Address as AddressValue, type AddressField, type AddressLocation, type AddressProvider, type AddressProviderRequest, type AddressSuggestion, type FormatAddressOptions } from './address.js';
|
|
4
|
+
export { DEFAULT_ADDRESS_ENDPOINT, setAddressProvider } from './address.provider.js';
|
|
5
|
+
export { createGooglePlacesProvider, createGooglePlacesProxy, GooglePlacesError, parseGooglePlace, type GooglePlace, type GooglePlaceAddressComponent, type GooglePlacesProviderOptions, type GooglePlacesProxyOptions } from './address.google.js';
|
|
6
|
+
export { addressTheme, setAddressTheme, useAddressTheme, type AddressTheme, type AddressThemeProps } from './address.theme.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as Address } from './Address.svelte';
|
|
2
|
+
export { ADDRESS_FIELDS, COUNTRY_CODES, addressCountryName, composeStreetLine, countryName, formatAddress, formatAddressLine, isAddressEmpty } from './address.js';
|
|
3
|
+
export { DEFAULT_ADDRESS_ENDPOINT, setAddressProvider } from './address.provider.js';
|
|
4
|
+
export { createGooglePlacesProvider, createGooglePlacesProxy, GooglePlacesError, parseGooglePlace } from './address.google.js';
|
|
5
|
+
export { addressTheme, setAddressTheme, useAddressTheme } from './address.theme.js';
|