@reykjavik/webtools 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,452 @@
1
+ # @reykjavik/webtools
2
+
3
+ > **Warning** This repo is still very much WIP. The npm package has **NOT**
4
+ > been published yet.
5
+ >
6
+ > See [Project Prep TODO](https://github.com/reykjavikcity/webtools/issues/1)
7
+ > for what's planned
8
+
9
+ Miscellaneous JavaScript/TypeScript helpers used by Reykjavík City's web dev
10
+ teams.
11
+
12
+ This library is split up into multple individual modules to help keep your
13
+ bundles slim and aid tree-shaking.
14
+
15
+ ```
16
+ yarn add @reykjavik/webtools
17
+ ```
18
+
19
+ **Table of Contents:**
20
+
21
+ <!-- prettier-ignore-start -->
22
+
23
+ - [`@reykjavik/webtools/http`](#reykjavikwebtoolshttp)
24
+ - [HTTP Status Codes](#http-status-codes)
25
+ - [Types for HTTP Status code groups](#types-for-http-status-code-groups)
26
+ - [`cacheControl` helper](#cachecontrol-helper)
27
+ - [Type `TTLConfig`](#type-ttlconfig)
28
+ - [`@reykjavik/webtools/next/http`](#reykjavikwebtoolsnexthttp)
29
+ - [`makeErrorizeAppHOC`](#makeerrorizeapphoc)
30
+ - [`showErrorPage` helper](#showerrorpage-helper)
31
+ - [`notModified304` helper](#notmodified304-helper)
32
+ - [`@reykjavik/webtools/CookieHubConsent`](#reykjavikwebtoolscookiehubconsent)
33
+ - [`CookieHubProvider` component](#cookiehubprovider-component)
34
+ - [`useCookieHubConsent`](#usecookiehubconsent)
35
+ - [`@reykjavik/webtools/next/SiteImprove`](#reykjavikwebtoolsnextsiteimprove)
36
+ - [`SiteImprove` component](#siteimprove-component)
37
+ - [`pingSiteImprove` helper](#pingsiteimprove-helper)
38
+ - [Changelog](#changelog)
39
+
40
+ <!-- prettier-ignore-start -->
41
+
42
+ ---
43
+
44
+ ## `@reykjavik/webtools/http`
45
+
46
+ Various framework agnostic helpers for leveraging HTTP magic.
47
+
48
+ ### HTTP Status Codes
49
+
50
+ The most common HTTP status codes are exported with human-readable names.
51
+
52
+ - `HTTP_200_OK`
53
+ - `HTTP_201_Created`
54
+ - `HTTP_202_Accepted`
55
+ - `HTTP_301_MovedPermanently`
56
+ - `HTTP_302_Found`
57
+ - `HTTP_303_SeeOther`
58
+ - `HTTP_304_NotModified`
59
+ - `HTTP_307_TemporaryRedirect`
60
+ - `HTTP_308_PermanentRedirect`
61
+ - `HTTP_400_BadRequest`
62
+ - `HTTP_401_Unauthorized`
63
+ - `HTTP_403_Forbidden`
64
+ - `HTTP_404_NotFound`
65
+ - `HTTP_410_Gone`
66
+ - `HTTP_418_ImATeapot`
67
+ - `HTTP_500_InternalServerError`
68
+
69
+ ### Types for HTTP Status code groups
70
+
71
+ These type unions are useful when writing HTTP helper functions and error
72
+ handling, etc.
73
+
74
+ - `HTTP_SUCCESS` (2xx)
75
+ - `HTTP_REDIRECTION` (3xx)
76
+ - `HTTP_NOTMODIFIED` (304)
77
+ - `HTTP_CLIENT_ERROR` (4xx)
78
+ - `HTTP_NOT_FOUND` (400, 404)
79
+ - `HTTP_BANNED` (401, 403)
80
+ - `HTTP_SERVER_ERROR` (5xx)
81
+ - `HTTP_ERROR` (4xx, 5xx)
82
+ - `HTTP_STATUS` (all of the above)
83
+
84
+ ### `cacheControl` helper
85
+
86
+ **Syntax:**
87
+ `cacheConrol(response: ServerResponse | { res: ServerResponse }, ttlCfg: TTLConfig, eTag?: string|number): void`
88
+
89
+ Use this function to quickly set the `Cache-Control` header with a `max-age=`
90
+ on a HTTP response.
91
+
92
+ ```js
93
+ import { cacheControl } from '@reykjavik/webtools/http';
94
+
95
+ // ...then inside an API handler
96
+ // or a framework's data loader function
97
+ cacheControl(res, '4h');
98
+ // ...then set statusCode and send data
99
+ ```
100
+
101
+ The directives `private` and `immutable` are used by by default.
102
+
103
+ Use the optional `eTag` parameter if you intend to
104
+ [handle conditional requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests).
105
+
106
+ #### Type `TTLConfig`
107
+
108
+ ```js
109
+ import type { TTLConfig } from '@reykjavik/webtools/http';
110
+
111
+ const myTTL1: TTLConfig = '4s';
112
+ const myTTL2: TTLConfig = { maxAge: '4s' };
113
+ ```
114
+
115
+ The `ttlCfg` parameter is either a bare `TTL` (max-age) value:
116
+
117
+ - `number` — seconds
118
+ - `"${number}${'s'|'m'|'h'|'d'|'w'}"` — gets converted to seconds
119
+
120
+ …one of these `TTLKeywords`:
121
+
122
+ - `"permanent"` — an alias for `maxAge: '365d'`
123
+ - `"no-cache"` — disables caching
124
+ - `"unset"` — removes the header altogether
125
+
126
+ …or a more complex `TTLConfig` object with the following properties:
127
+
128
+ **`TTLConfig.maxAge: TTL | TTLKeywords`** (required)
129
+
130
+ Sets the `max-age=` directive. See above definitions
131
+
132
+ (NOTE: Second values of zero or less get converted to `"no-cache"`.)
133
+
134
+ **`TTLConfig.staleWhileRevalidate?: TTL`**
135
+
136
+ If set to a positive value then `stale-while-revalidate=` is added to the
137
+ response header
138
+
139
+ **`TTLConfig.staleIfError?: TTL`**
140
+
141
+ If set to a positive value then `stale-if-error=` is added to the response
142
+ header
143
+
144
+ **`TTLConfig.publ?: boolean`**
145
+
146
+ Sets the response caching as "public", instead of the default "private"
147
+
148
+ **`TTLConfig.stability?: 'revalidate' | 'immutable' | 'normal'`**
149
+
150
+ Allows setting a "must-revalidate" flag instead of the default "immutable". A
151
+ value of `"normal"` omits the flagging and falls back to HTTP's default
152
+ behavior.
153
+
154
+ ---
155
+
156
+ ## `@reykjavik/webtools/next/http`
157
+
158
+ Contains HTTP helpers for Next.js projects
159
+
160
+ Re-exports all of the base [http module](#reykjaviktoolshttp)'s exports, for
161
+ convenience
162
+
163
+ ### `makeErrorizeAppHOC`
164
+
165
+ **Syntax:**
166
+ `makeErrorizeAppHOC(ErrorPageComponent: ComponentType<EP>): (App: AppType<P>) => AppType<P | EP>`
167
+
168
+ Hhigher-order component (HOC) factory for Next.js App compnents to handle
169
+ cases when `getServerSideProps` returns an `__error` prop with `statusCode`
170
+ and optional friendly `message`.
171
+
172
+ Pass in an error-page compnent, and receive a HOC function that wraps any
173
+ Next.js App compnent. The HOC also has a type-safe
174
+ [`.showErrorPage`](#showerrorizedpage-helper) helper method to use inside
175
+ `getServerSideProps` in order to trigger display of the error page.
176
+
177
+ Set up the error page for your app:
178
+
179
+ ```tsx
180
+ // src/helpers/myerrors.js
181
+
182
+ import {
183
+ makeErrorizeAppHOC,
184
+ ErrorProps,
185
+ InferErrorPageProps,
186
+ } from '@reykjavik/webtools/next/http';
187
+
188
+ type MyErrorPageProps = ErrorProps & {
189
+ /* ...custom props... */
190
+ };
191
+ const MyErrorPage = (props: MyErrorPageProps) => {
192
+ const { statusCode, message /* plus your custom props */ } = props;
193
+ return (
194
+ <div>
195
+ <h1>{statusCode}</h1>
196
+ {message && <p>{message}</p>}
197
+ </div>
198
+ );
199
+ };
200
+
201
+ // Generate and export the HOC
202
+ export const withMyErrorHandling = makeErrorizeAppHOC(MyErrorPage);
203
+ // Export the gSSP helper
204
+ export const showErrorPage = withMyErrorHandling.showErrorPage;
205
+ // Export the props type of the error page
206
+ export type ErrorPageProps = InferErrorPageProps<typeof showErrorPage>;
207
+ ```
208
+
209
+ Wrap `_app.tsx` with the HOC you generated:
210
+
211
+ ```jsx
212
+ // src/pages/_app.js
213
+
214
+ import { withMyErrorHandling } from '~/helpers/myerrors';
215
+
216
+ const App = ({ Component, pageProps }: AppProps<PageProps>) => {
217
+ // ...define your App component as normal...
218
+ };
219
+
220
+ export default withMyErrorHandling(App);
221
+ ```
222
+
223
+ Return errors inside your page/route modules, using `showErrorPage`
224
+
225
+ ```tsx
226
+ // src/pages/index.js
227
+
228
+ import type { GetServerSideProps } from 'next';
229
+ import { showErrorPage, ErrorPageProps } from '~/helpers/errors';
230
+
231
+ type MyPageProps = {};
232
+ // Export the page component
233
+ export default function MyPage(props: MyPageProps) {
234
+ // ...
235
+ }
236
+
237
+ export const getServerSideProps: GetServerSideProps<
238
+ MyPageProps | ErrorPageProps
239
+ > = async (ctx) => {
240
+ // ...fetch data from api
241
+ if (!apiRes.error === 'unauthorized') {
242
+ return showErrorPage(ctx.res, {
243
+ statusCode: HTTP_400_BadRequest,
244
+ // ...Add other custom MyErrorPage props
245
+ });
246
+ }
247
+ // ...return normal, happy page props.
248
+ };
249
+ ```
250
+
251
+ See more below
252
+
253
+ ### `showErrorPage` helper
254
+
255
+ **Syntax:**
256
+ `showErrorPage = (response: ServerResponse | NextContext, error: HTTP_ERROR | ErrorProps, ttl?: TTL | TTLConfig): void`
257
+
258
+ This method is attached to the HOC returned by
259
+ [`makeErrorizeAppHOC`](#makeerrorizeapphoc). Use it inside your pages'
260
+ `getServerSideProps` to return the appropriate an "error" props, including a
261
+ HTTP `statusCode`, etc.
262
+
263
+ ```js
264
+ import { showErrorPage, ErrorPageProps } from '~/helpers/myerrors';
265
+
266
+ // ...then, somewhere inside getServerSideProps
267
+ if (invalidParams) {
268
+ return showErrorPage(
269
+ res,
270
+ {
271
+ statusCode: HTTP_400_BadRequest,
272
+ message: 'You passed me bad params :-(', // optional message
273
+ // ...Add other custom MyErrorPage props
274
+ },
275
+ 'permanent'
276
+ );
277
+ }
278
+
279
+ if (!apiRes.error === 'unauthorized') {
280
+ // Optional `statusCode` shorthand signature, available if your
281
+ // error page has no required props (other than `statusCode`).
282
+ return showErrorPage(res, HTTP_403_Forbidden);
283
+ }
284
+
285
+ // ...return normal, happy page props.
286
+ ```
287
+
288
+ The `ttl` parameter defaults to `'2s'`, but you can pass any
289
+ [`TTLConfig`](#type-ttlconfig).
290
+
291
+ ### `notModified304` helper
292
+
293
+ **Syntax:** `notModified304(response: ServerResponse | NextContext): void`
294
+
295
+ Use this method to inside a `getServerSideProps` method (or API route) to
296
+ return a `HTTP_304_NotModified` response with an empty props object, in a way
297
+ that doesn't make TypeScript shout at you.
298
+
299
+ (Turns out that when a 304 status is returned, then Next.js doesn't even
300
+ attempt to render the Page compnoent, so the returned props don't matter.
301
+ TypeScript, however, doesn't know that.)
302
+
303
+ ```js
304
+ import { notModified304 } from '@reykjavik/webtools/next/http';
305
+
306
+ // ...then, somewhere inside getServerSideProps
307
+ const notModified = data.modifiedTimestamp === req.headers['if-none-match'];
308
+ if (notModified) {
309
+ return notModified304(res);
310
+ }
311
+ ```
312
+
313
+ ---
314
+
315
+ ## `@reykjavik/webtools/CookieHubConsent`
316
+
317
+ Contains React helpers for loading CookieHub's consent manager and reading
318
+ users' consent values.
319
+
320
+ ### `CookieHubProvider` component
321
+
322
+ This context provider component loads and initialises the CookieHub consent
323
+ management script and sets up a React state object with the relevant user
324
+ consent flags.
325
+
326
+ Wrap this provider around your component tree, and then use the
327
+ [`useCookieHubConsent()` hook](#usecookiehubconsent) to retrieve live consent
328
+ information, whereever you wish to set GDPR-affected cookies or perform any
329
+ sort of tracking/logging.
330
+
331
+ ```js
332
+ import { CookieHubProvider } from '@reykjavik/webtools/CookieHubConsent';
333
+
334
+ import { AnalyticsStuff } from '../components/AnalyticsStuff';
335
+
336
+ // Maybe move this to an Env variable, or something...
337
+ const cookiehubAccountId = '[ACCOUNT_ID]'; // e.g. "a4b3c2d1"
338
+
339
+ export default function App() {
340
+ return (
341
+ <CookieHubProvider accountId={cookiehubAccountId}>
342
+ <div>
343
+ <p>...my App UI...</p>
344
+ <AnalyticsStuff />
345
+ </div>
346
+ </CookieHubProvider>
347
+ );
348
+ }
349
+ ```
350
+
351
+ **Props:**
352
+
353
+ The Component's props have detailed JSDoc comments (displayed in your code
354
+ editor), but there's a brief summary:
355
+
356
+ - `accountId?: string` — Your CookieHub account ID. (alternative to
357
+ `scriptUrl` prop).
358
+ - `scriptUrl?: string` — The full CookieHub embed script URL. (alternative to
359
+ `accountId` prop).
360
+ - `options?: CookieHubOptions` — Raw CookieHub options object that gets used
361
+ when the script initializes.
362
+ - `onError?: OnErrorEventHandlerNonNull` — Fires if loading the script failed.
363
+
364
+ ### `useCookieHubConsent`
365
+
366
+ **Syntax:** `useCookieHubConsent(): Record<CookieHubCategory, boolean>`
367
+
368
+ Returns up-to-date cookie consent `boolean` flags. For use in React components
369
+ or hook functions.
370
+
371
+ ```js
372
+ import { useCookieHubConsent } from '@reykjavik/webtools/CookieHubConsent';
373
+
374
+ export const AnalyticsStuff = (props) => {
375
+ const consent = useCookieHubConsent();
376
+ if (!consent.analytics) {
377
+ return null;
378
+ }
379
+ // Perform analytics...
380
+ };
381
+ ```
382
+
383
+ If the `CookieHubProvider` is missing from the VDOM tree above your component,
384
+ this hook will return an empty object.
385
+
386
+ ---
387
+
388
+ ## `@reykjavik/webtools/next/SiteImprove`
389
+
390
+ Contains React helpers for loading SiteImprove's analytics scripts in Next.js
391
+ applications and perform custom event tracking.
392
+
393
+ ### `SiteImprove` component
394
+
395
+ A component for loading a SiteImprove analytics script and set up page-view
396
+ tracking across Next.js routes.
397
+
398
+ ```js
399
+ import { SiteImprove } from '@reykjavik/webtools/next/SiteImprove';
400
+
401
+ const siteImproveAccountId = '[ACCOUNT_ID]'; // e.g. "7654321"
402
+ ```
403
+
404
+ The component has an optional `hasConsented` prop which can be used to
405
+ forcefully suppress loading the analytics script.
406
+
407
+ In dev mode it does NOT load the SiteImprove script and only logs page-view
408
+ events to the console.
409
+
410
+ **Props:**
411
+
412
+ The Component's props have detailed JSDoc comments (displayed in your code
413
+ editor), but there's a brief summary:
414
+
415
+ - `accountId?: string` — Your SiteImprove account ID. (alternative to
416
+ `scriptUrl` prop).
417
+ - `scriptUrl?: string` — The full SiteImprove analytics script URL.
418
+ (alternative to `accountId` prop).
419
+ - `hasConstented?: boolean` — Manual GDPR 'analytics' consent flag. Allows
420
+ hard opt-out, but defers to
421
+ [`CookieHubProvider` values](#usecookiehubconsent) by default.
422
+ - `onLoad?: (e: unknown) => void` — Fires when the script has loaded.
423
+ - `onError?: (e: unknown) => void` — Fires if loading the script failed.
424
+
425
+ ### `pingSiteImprove` helper
426
+
427
+ **Syntax:**
428
+ `pingSiteImprove(category: string, action: string, label?: string): void`
429
+
430
+ A small helper for tracking custom UI events and reporting them to SiteImrove.
431
+
432
+ It safely manages GDPR consent, so you can use it unconditionally.
433
+
434
+ ```js
435
+ import { pingSiteImprove } from '@reykjavik/webtools/next/SiteImprove';
436
+
437
+ const handleSubmit = () => {
438
+ // perform submit action...
439
+ if (success) {
440
+ pingSiteImprove('application', 'add_new');
441
+ }
442
+ };
443
+ ```
444
+
445
+ In dev mode it only logs tracking events to the console.
446
+
447
+ ---
448
+
449
+ ## Changelog
450
+
451
+ See
452
+ [CHANGELOG.md](https://github.com/reykjavikcity/webtools/blob/main/CHANGELOG.md)
@@ -0,0 +1,231 @@
1
+ import { ReactNode } from 'react';
2
+ import { EitherObj } from '@reykjavik/hanna-utils';
3
+ declare global {
4
+ interface Window {
5
+ cookiehub: CookieHub;
6
+ }
7
+ }
8
+ type CookieHub = {
9
+ /**
10
+ * Used to initialize, and configure, CookieHub.
11
+ *
12
+ * (Thin wrapper for `window.cookiehub.initialize`)
13
+ *
14
+ * @see https://support.cookiehub.com/article/86-methods-functions
15
+ */
16
+ load(options?: CookieHubOptions): void;
17
+ /**
18
+ * Used to initialize, and configure, CookieHub.
19
+ *
20
+ * @see https://support.cookiehub.com/article/86-methods-functions
21
+ */
22
+ initialize(options?: CookieHubOptions): void;
23
+ /**
24
+ * Used to check if the user has already made cookie choices.
25
+ *
26
+ * @see https://support.cookiehub.com/article/86-methods-functions
27
+ */
28
+ hasAnswered(): boolean;
29
+ /**
30
+ * Used to check if the user has allowed the cookie category specified in
31
+ * the category parameter.
32
+ *
33
+ * @see https://support.cookiehub.com/article/86-methods-functions
34
+ */
35
+ hasConsented(category: CookieHubCategory): boolean;
36
+ /**
37
+ * Used to check if the CookieHub script has been initialized
38
+ *
39
+ * @see https://support.cookiehub.com/article/86-methods-functions
40
+ */
41
+ hasInitialized(): boolean;
42
+ /**
43
+ * Open the CookieHub dialog.
44
+ *
45
+ * @see https://support.cookiehub.com/article/86-methods-functions
46
+ */
47
+ openDialog(): void;
48
+ /**
49
+ * Close the CookieHub dialog if it's still open.
50
+ *
51
+ * @see https://support.cookiehub.com/article/86-methods-functions
52
+ */
53
+ closeDialog(): void;
54
+ /**
55
+ * Open the CookieHub settings dialog. This may be useful if you choose to
56
+ * hide the settings icon which is usually used to open the CookieHub
57
+ * settings dialog and want to create a custom link or button to open the
58
+ * dialog instead.
59
+ *
60
+ * @see https://support.cookiehub.com/article/86-methods-functions
61
+ */
62
+ openSettings(): void;
63
+ /**
64
+ * Close the CookieHub settings dialog.
65
+ *
66
+ * @see https://support.cookiehub.com/article/86-methods-functions
67
+ */
68
+ closeSettings(): void;
69
+ /**
70
+ * Denys all cookie categories.
71
+ *
72
+ * @see https://support.cookiehub.com/article/86-methods-functions
73
+ */
74
+ denyAll(): void;
75
+ /**
76
+ * Allows all cookie categories.
77
+ *
78
+ * @see https://support.cookiehub.com/article/86-methods-functions
79
+ */
80
+ allowAll(): void;
81
+ };
82
+ type CookieHubCategory = 'necessary' | 'preferences' | 'analytics' | 'marketing' | 'uncategorized';
83
+ type CookieHubOptions = {
84
+ /**
85
+ * Fired when CookieHub has finished loading.
86
+ *
87
+ * @see https://support.cookiehub.com/article/87-events
88
+ */
89
+ onInitialise?: (this: CookieHub, status: CookiehubState) => void;
90
+ /**
91
+ * Fired any time users make changes to cookie choices and click the
92
+ * Save Settings or if the Allow All Cookies button is clicked.
93
+ *
94
+ * @see https://support.cookiehub.com/article/87-events
95
+ */
96
+ onStatusChange?: (this: CookieHub, status: CookiehubState, previousStatus: CookiehubState) => void;
97
+ /**
98
+ * Fired any time a cookie category is allowed that was previously disallowed.
99
+ *
100
+ * @see https://support.cookiehub.com/article/87-events
101
+ */
102
+ onAllow?: (this: CookieHub, category: CookieHubCategory) => void;
103
+ /**
104
+ * Fired any time a cookie category consent is revoked for a category that
105
+ * was previously allowed.
106
+ *
107
+ * @see https://support.cookiehub.com/article/87-events
108
+ */
109
+ onRevoke?: (this: CookieHub, category: CookieHubCategory) => void;
110
+ dialog?: {
111
+ /**
112
+ * Controls the display of the action buttons in the popup dialog.
113
+ *
114
+ * @see https://support.cookiehub.com/article/128-changing-the-order-of-action-buttons
115
+ */
116
+ actions?: Array<'allow' | 'deny' | 'settings'>;
117
+ };
118
+ cookie?: {
119
+ /**
120
+ * Empty string (`''`) will instruct the browser to set the cookie on
121
+ * the current domain instead of the top level domain which is the
122
+ * default value.
123
+ *
124
+ * @see https://support.cookiehub.com/article/85-cookiehub-on-multiple-domains-hosts
125
+ */
126
+ domain?: string;
127
+ /**
128
+ * Controls the cookie behavior and access for the cookiehub cookie
129
+ *
130
+ * Possible values are:
131
+ *
132
+ * - **Lax** (Default): Allows pages on the domain and third party links
133
+ * to access the cookie. This is the default setting for CookieHub.
134
+ * - **Strict**: Only allows pages on the domain that set the cookie to
135
+ * access it. Links from third parties won’t be able to access the
136
+ * cookie.
137
+ * - **None**: No domain limitations and third-party cookies can fire.
138
+ *
139
+ * @see https://support.cookiehub.com/article/84-cookie-security-and-the-samesite-attribute
140
+ */
141
+ sameSite?: 'Strict' | 'Lax' | 'None';
142
+ /**
143
+ * If the Secure attribute is set to true, the cookie will only be accessible
144
+ * if the page being loaded is loaded over a secure connection.
145
+ *
146
+ * Defaults to `false` but it's recommended to set it to true
147
+ *
148
+ * @see https://support.cookiehub.com/article/84-cookie-security-and-the-samesite-attribute
149
+ */
150
+ secure?: boolean;
151
+ };
152
+ };
153
+ type CookiehubState = {
154
+ answered: boolean;
155
+ preconsent: boolean;
156
+ revision: number;
157
+ dnt: boolean;
158
+ allowSale: boolean;
159
+ implict: boolean;
160
+ region: string;
161
+ token: string;
162
+ timestamp: Date;
163
+ categories: Array<CookieHubCategoryState>;
164
+ };
165
+ type CookieHubCategoryState = {
166
+ cid: number;
167
+ id: CookieHubCategory;
168
+ value: boolean;
169
+ preconsent: boolean;
170
+ fired: boolean;
171
+ };
172
+ type CookieHubContextState = {
173
+ consent: Record<Exclude<CookieHubCategory, 'necessary'>, boolean>;
174
+ };
175
+ export type CookieHubProviderProps = EitherObj<{
176
+ /**
177
+ * Yuour CookieHub account ID.
178
+ *
179
+ * It's a random-looking alpha-numerical string, and it can usually be
180
+ * extracted from the script embed URL like this:
181
+ * `"https://cookiehub.net/c2/[ACCOUNT_ID].js"`
182
+ *
183
+ * @see https://support.cookiehub.com/article/155-manual-implementation-guide
184
+ */
185
+ accountId: string;
186
+ }, {
187
+ /**
188
+ * The full CookieHub embed script URL.
189
+ *
190
+ * Something like `"https://cookiehub.net/c2/[ACCOUNT_ID].js"`
191
+ *
192
+ * @see https://support.cookiehub.com/article/155-manual-implementation-guide
193
+ */
194
+ scriptUrl: string;
195
+ }> & {
196
+ children: ReactNode;
197
+ /**
198
+ * Custom callback that fires when CookieHub has initialized.
199
+ *
200
+ * To subscribe to other events run:
201
+ *
202
+ * ```js
203
+ * window.cookiehub.initialize({
204
+ * // Event handlers other than `onInitialize`
205
+ * })
206
+ * ```
207
+ *
208
+ * @see https://support.cookiehub.com/article/87-events
209
+ */
210
+ options?: CookieHubOptions;
211
+ /**
212
+ * Error callback for if the CookieHub script fails to load.
213
+ */
214
+ onError?: OnErrorEventHandlerNonNull;
215
+ };
216
+ /**
217
+ * This context provider component loads and initialises the CookieHub consent
218
+ * management script and sets up a React state object with the relevant user
219
+ * consent flags.
220
+ *
221
+ * @see https://github.com/reykjavikcity/webtools/tree/v0.1##cookiehubprovider-component
222
+ */
223
+ export declare const CookieHubProvider: (props: CookieHubProviderProps) => JSX.Element;
224
+ /**
225
+ * Returns up-to-date cookie consent flags. For use in React components or hook
226
+ * functions.
227
+ *
228
+ * @see https://github.com/reykjavikcity/webtools/tree/v0.1##usecookiehubconsent
229
+ */
230
+ export declare const useCookieHubConsent: () => Partial<CookieHubContextState['consent']>;
231
+ export {};