@autobusal/providers 1.40.7 → 1.41.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.41.0 (2026-08-29)
4
+
5
+ - The app-shell title is set through document.title instead of a rendered <title> element - React 19 does not deduplicate titles across components, so the shell's and the page's both reached <head>, which is what Meta's cleanup was deleting one of (Sentry BUSMAGUS-7).
6
+
3
7
  ## 1.40.7 (2026-08-28)
4
8
 
5
9
  - useReferralTouch: the web finally reads ?ref= - touch on landing, token in localStorage (referral_token field: the BFF strips top-level token); storedReferral() exported for checkout replay.
package/Setup/Preload.tsx CHANGED
@@ -1,3 +1,4 @@
1
+ import { useEffect } from 'react';
1
2
  import { JsonLd, setServerToday } from '@autobusal/common';
2
3
  import { SettingsData } from '../types/settings';
3
4
  import { useSystemTheme } from '@autobusal/hooks';
@@ -8,12 +9,28 @@ interface Props {
8
9
  }
9
10
 
10
11
  // React 19 automatically hoists any <title>/<meta>/<link> rendered anywhere
11
- // in the tree into <head> (deduplicating <title> and meta[name=...], last
12
- // render wins) - no wrapper component needed. Replaced react-helmet, which
13
- // had gone silently non-functional under React 19 (see @autobusal/common's
14
- // Meta.tsx for how this was diagnosed). This <title> is the app-shell
15
- // fallback rendered above the router; a page's own <Meta title=...> renders
16
- // deeper in the tree and correctly overrides it once data loads.
12
+ // in the tree into <head> - no wrapper component needed. Replaced
13
+ // react-helmet, which had gone silently non-functional under React 19 (see
14
+ // @autobusal/common's Meta.tsx for how this was diagnosed).
15
+ //
16
+ // Edited: Claude - Date: 2026-08-29 (Sentry BUSMAGUS-7)
17
+ //
18
+ // The shell title is set IMPERATIVELY, and is no longer a <title> element.
19
+ //
20
+ // It used to be `<title>{ company }</title>` rendered here, above the
21
+ // router, on the stated assumption that React 19 deduplicates titles and
22
+ // the page's own deeper <Meta title=...> would override it. It does not:
23
+ // both are hoisted and BOTH end up in <head>, which is why Meta's cleanup
24
+ // was written to keep one element and delete the others - and deleting the
25
+ // other one meant deleting a node React owned, leaving its fiber pointing
26
+ // at a detached element. The next render or unmount then called
27
+ // removeChild on a null parent: BUSMAGUS-7, an uncaught TypeError that
28
+ // aborts the navigation in flight.
29
+ //
30
+ // Setting document.title directly competes with nothing: a page's <Meta>
31
+ // renders the one and only <title> ELEMENT, and React sets the document
32
+ // title from it when it commits. The guard keeps this a FALLBACK - if a
33
+ // page has already put its own title up, the shell must not overwrite it.
17
34
  const Preload = ({ data, children }: Props): JSX.Element => {
18
35
  // Edited: Ferjolt Ozuni - Date: 2026-08-03
19
36
  // Hand the booking calendar the SERVER's idea of today, before anything
@@ -23,6 +40,13 @@ const Preload = ({ data, children }: Props): JSX.Element => {
23
40
  // sold them quite happily.
24
41
  setServerToday(data.today);
25
42
 
43
+ // the app-shell title, for the moment before a page's own <Meta> mounts
44
+ useEffect(() => {
45
+ if (!document.head.querySelector('title')) {
46
+ document.title = data.preferences.company;
47
+ }
48
+ }, [ data.preferences.company ]);
49
+
26
50
  // we arrange the font family names before inserting them
27
51
  const fontTitle = data.theme.fontFamily.title.replace(/ /g, '+');
28
52
  const fontContent = data.theme.fontFamily.content.replace(/ /g, '+');
@@ -67,8 +91,6 @@ const Preload = ({ data, children }: Props): JSX.Element => {
67
91
 
68
92
  return (
69
93
  <>
70
- <title>{ data.preferences.company }</title>
71
-
72
94
  <link rel="apple-touch-icon" sizes="180x180" href={ `${ data.url }/favicons/apple-touch-icon.png` } />
73
95
  <link rel="icon" type="image/png" sizes="32x32" href={ `${ data.url }/favicons/favicon-32x32.png` } />
74
96
  <link rel="icon" type="image/png" sizes="16x16" href={ `${ data.url }/favicons/favicon-16x16.png` } />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/providers",
3
- "version": "1.40.7",
3
+ "version": "1.41.1",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts"
package/types/settings.ts CHANGED
@@ -406,6 +406,21 @@ export interface GatewayCredentials<T> {
406
406
  mode: 'sandbox' | 'production'
407
407
  sandbox: T
408
408
  production: T
409
+
410
+ /**
411
+ * The CARD SURCHARGE this gateway carries on this brand, as a percentage
412
+ * (5 means 5%).
413
+ *
414
+ * Claude - 2026-08-29 (ruling by Ferjolt): what the payer is charged on
415
+ * top of what they owe, for settling online - see obtapi's
416
+ * App\Libraries\Payments\Surcharge.
417
+ *
418
+ * BESIDE the credentials rather than inside `sandbox`/`production`,
419
+ * deliberately: a commercial term is not a credential, and it must not
420
+ * change when a brand flips to production. Optional because no existing
421
+ * brand has one, which reads as no surcharge.
422
+ */
423
+ surcharge?: number
409
424
  }
410
425
 
411
426
  export interface LabelPayments {