@artstorefronts/arthelper-nav 0.1.0-alpha.5 → 0.1.0-alpha.7

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 CHANGED
@@ -67,8 +67,20 @@ is obviously this app, stop and ask — an id is added by an operator, not by yo
67
67
  Without this, a user who collapsed the bar gets an expanded bar in the first byte and a
68
68
  56px jump after hydration.
69
69
 
70
- 6. **Optionally pass `onAppClick`** to emit your own analytics. The package imports no
71
- analytics library, and one callback covers both the desktop tiles and the mobile dropdown.
70
+ 6. **Pass `onAppClick`** so this app's clicks reach the fleet-wide chart. The package ships
71
+ no analytics SDK — transport, identity and consent stay with you — but it does export the
72
+ event's shape, so use it rather than hand-writing the payload:
73
+
74
+ ```ts
75
+ import { suiteNavClickEvent } from '@artstorefronts/arthelper-nav';
76
+
77
+ onAppClick={(args) => yourTracker.track(...suiteNavClickEvent(args, '<this-app-id>'))}
78
+ ```
79
+
80
+ Hand-writing it is how a satellite ends up sending `app_id` instead of `target_app_id`,
81
+ which does not fail — it silently splits the chart. One callback covers both the desktop
82
+ tiles and the mobile dropdown. If your tracker batches, flush on the way out: a tile is a
83
+ real cross-app `<a href>`, so the document is replaced and a queued batch dies with it.
72
84
 
73
85
  ## `configUrl` — the mistake to avoid
74
86
 
@@ -190,23 +202,12 @@ Peer dependencies (from `package.json` — install these yourself, they are not
190
202
  }
191
203
  ```
192
204
 
193
- > **Getting a change released.** There is no tag and no manual release step: bump the
194
- > version in `packages/nav/package.json` in the PR that changes the package, and merging
195
- > to `develop` publishes it. CI publishes only when that version is absent from the
196
- > registry, and a PR that changes the published surface while leaving the version alone
197
- > fails its own check — so a change cannot quietly land without reaching you.
198
- >
199
- > **Testing an unreleased change.** Link the workspace, or use a path dependency:
200
- >
201
- > ```bash
202
- > cd packages/nav && yarn link
203
- > cd ../../../<satellite> && yarn link @artstorefronts/arthelper-nav
204
- > ```
205
- >
206
- > `react` and `react-dom` are peer dependencies, so make sure the satellite's bundler
207
- > resolves a single copy of React — a linked package pulling in its own is the usual
208
- > cause of the duplicate-React hooks error. `npm pack` plus installing the tarball avoids
209
- > that failure mode entirely and resolves more like the real thing.
205
+ > **Need a change to the bar itself?** Its look, layout and behaviour ship in this package
206
+ > rather than being configurable — see [Theming and the wordmark](#theming-and-the-wordmark)
207
+ > — so changing them means a new release. Ask the ArtHelper team; releases are automatic and
208
+ > quick. What you _can_ change without one is which apps appear, in what order and pointing
209
+ > where: that lives in the config row, editable from ArtHelper's admin screen and picked up
210
+ > on next load.
210
211
 
211
212
  ## Minimal mounting example
212
213
 
@@ -317,23 +318,37 @@ This is the same derivation both in-monorepo hosts (`client/`, `town-square/`) u
317
318
 
318
319
  ## `onAppClick`: the analytics seam
319
320
 
320
- The package imports no analytics library of any kind. `onAppClick` is the one hook
321
- through which a host wires its own analytics — it fires immediately before navigation,
322
- from **both** the desktop tile row and the mobile dropdown, so one callback covers both
323
- surfaces:
321
+ `onAppClick` fires immediately before navigation, from one shared handler behind both the
322
+ desktop tile row and the mobile dropdown — so it covers both surfaces and cannot
323
+ double-fire.
324
+
325
+ **The package ships no analytics SDK, deliberately.** Bundling one would run a second
326
+ instance alongside yours, racing it on device id and session, and would emit without your
327
+ identity or consent handling — producing clicks that cannot be joined to users. Transport,
328
+ identity and consent are yours.
329
+
330
+ What the package does own is the event's shape, because that is the part that drifts:
324
331
 
325
332
  ```ts
333
+ import { suiteNavClickEvent } from '@artstorefronts/arthelper-nav';
334
+
326
335
  <NavProvider
327
- activeAppId="my-app"
328
336
  configUrl={NAV_CONFIG_URL}
329
- onAppClick={({ app, activeAppId, collapsed }) => {
330
- myAnalytics.track('suite_nav_app_clicked', { targetAppId: app.id, activeAppId, collapsed });
331
- }}
337
+ activeAppId="art-books"
338
+ onAppClick={(args) => amplitude.track(...suiteNavClickEvent(args, 'art_books'))}
332
339
  >
333
340
  ```
334
341
 
335
- Navigation itself happens via a real `<a href>` the browser follows natively —
336
- `onAppClick` never intercepts or prevents it.
342
+ It returns a `[name, properties]` pair, so the two cannot be paired wrongly. Properties are
343
+ `target_app_id` (the app clicked — the dimension click-throughs group on), `source_app`
344
+ (this app, passed in because hosts sharing a product surface share an `activeAppId` and so
345
+ cannot be told apart by it), and `collapsed`.
346
+
347
+ `SUITE_NAV_CLICK_EVENT` is exported too if your tracker needs the name separately.
348
+
349
+ **If your tracker batches, flush on the way out.** A tile is a real cross-app `<a href>`, so
350
+ the document is replaced and a queued batch dies with it — both ArtHelper hosts use their
351
+ tracker's on-exit variant for exactly this reason.
337
352
 
338
353
  ## SSR and the collapsed cookie
339
354
 
@@ -0,0 +1,42 @@
1
+ import type { NavAppClickArgs } from './types.js';
2
+ /**
3
+ * The one spelling of the suite bar's click event.
4
+ *
5
+ * The package deliberately ships no analytics SDK. Bundling one would run a second
6
+ * instance alongside the host's — racing it on device id and session — and would emit
7
+ * without the host's identity or consent handling, producing clicks that cannot be joined
8
+ * to users. Transport, identity and consent stay with the host; only the event's shape
9
+ * lives here.
10
+ *
11
+ * What that leaves is a drift risk, and it is the whole reason this helper exists: a
12
+ * satellite that hand-writes `app_id` instead of `target_app_id`, or renames the event,
13
+ * silently splits the fleet-wide chart rather than failing. Name and properties travel
14
+ * together as one value so the two cannot be paired wrongly.
15
+ */
16
+ declare const SUITE_NAV_CLICK_EVENT = "suite_nav_app_clicked";
17
+ type SuiteNavClickProperties<TSource extends string> = {
18
+ /** Catalog id of the app that was clicked — the dimension click-throughs group on. */
19
+ target_app_id: string;
20
+ /**
21
+ * Which host emitted the click. Passed in rather than read off `activeAppId`, because
22
+ * hosts that are one product surface share an id — ArtHelper's client and town-square
23
+ * both declare `home`, so `activeAppId` cannot tell them apart.
24
+ */
25
+ source_app: TSource;
26
+ /** Whether the bar was collapsed at click time. */
27
+ collapsed: boolean;
28
+ };
29
+ /**
30
+ * Builds the event as a `[name, properties]` pair, ready to spread into a tracker:
31
+ *
32
+ * ```ts
33
+ * onAppClick={(args) => amplitude.track(...suiteNavClickEvent(args, 'art_books'))}
34
+ * ```
35
+ *
36
+ * `TSource` is generic so the literal survives: a host whose tracker types `source_app` as
37
+ * a union of known apps still typechecks, which a widened `string` would not.
38
+ */
39
+ declare function suiteNavClickEvent<TSource extends string>(args: NavAppClickArgs, sourceApp: TSource): [typeof SUITE_NAV_CLICK_EVENT, SuiteNavClickProperties<TSource>];
40
+ export { SUITE_NAV_CLICK_EVENT, suiteNavClickEvent };
41
+ export type { SuiteNavClickProperties };
42
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,qBAAqB,0BAA0B,CAAC;AAKtD,KAAK,uBAAuB,CAAC,OAAO,SAAS,MAAM,IAAI;IACrD,sFAAsF;IACtF,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;;;;;GASG;AACH,iBAAS,kBAAkB,CAAC,OAAO,SAAS,MAAM,EAChD,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,OAAO,GACjB,CAAC,OAAO,qBAAqB,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAElE;AAED,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;AACrD,YAAY,EAAE,uBAAuB,EAAE,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The one spelling of the suite bar's click event.
3
+ *
4
+ * The package deliberately ships no analytics SDK. Bundling one would run a second
5
+ * instance alongside the host's — racing it on device id and session — and would emit
6
+ * without the host's identity or consent handling, producing clicks that cannot be joined
7
+ * to users. Transport, identity and consent stay with the host; only the event's shape
8
+ * lives here.
9
+ *
10
+ * What that leaves is a drift risk, and it is the whole reason this helper exists: a
11
+ * satellite that hand-writes `app_id` instead of `target_app_id`, or renames the event,
12
+ * silently splits the fleet-wide chart rather than failing. Name and properties travel
13
+ * together as one value so the two cannot be paired wrongly.
14
+ */
15
+ const SUITE_NAV_CLICK_EVENT = 'suite_nav_app_clicked';
16
+ /**
17
+ * Builds the event as a `[name, properties]` pair, ready to spread into a tracker:
18
+ *
19
+ * ```ts
20
+ * onAppClick={(args) => amplitude.track(...suiteNavClickEvent(args, 'art_books'))}
21
+ * ```
22
+ *
23
+ * `TSource` is generic so the literal survives: a host whose tracker types `source_app` as
24
+ * a union of known apps still typechecks, which a widened `string` would not.
25
+ */
26
+ function suiteNavClickEvent(args, sourceApp) {
27
+ return [SUITE_NAV_CLICK_EVENT, { target_app_id: args.app.id, source_app: sourceApp, collapsed: args.collapsed }];
28
+ }
29
+ export { SUITE_NAV_CLICK_EVENT, suiteNavClickEvent };
30
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAkBtD;;;;;;;;;GASG;AACH,SAAS,kBAAkB,CACzB,IAAqB,EACrB,SAAkB;IAElB,OAAO,CAAC,qBAAqB,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AACnH,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,CAAC"}
package/dist/index.css CHANGED
@@ -77,10 +77,12 @@
77
77
  * the wordmark changing typeface as you move between apps, and any family without a
78
78
  * real 600 gets faux-bolded on top.
79
79
  *
80
- * `-webkit-font-smoothing` is pinned for the same reason: a host that sets
81
- * `antialiased` on its body thins the bar's text on macOS, so the same 600 weight
82
- * looks lighter in that app than the next. `auto` is the default the design was
83
- * approved against.
80
+ * Both smoothing properties are pinned for the same reason: a host that sets
81
+ * `antialiased` on its body thins the bar's text on macOS, so the same 600 weight looks
82
+ * lighter in that app than the next. town-square does exactly that — `<body
83
+ * className="antialiased">` — and Tailwind's utility sets BOTH `-webkit-font-smoothing`
84
+ * and `-moz-osx-font-smoothing`, so countering only the webkit half leaves Firefox still
85
+ * inheriting `grayscale`. `auto` is the default the design was approved against.
84
86
  *
85
87
  * Set on every root the package renders — the bar, the docked trigger (which lives in
86
88
  * the host's own header) and the fixed mobile panel — because only the first of those
@@ -95,6 +97,7 @@
95
97
  Arial,
96
98
  sans-serif;
97
99
  -webkit-font-smoothing: auto;
100
+ -moz-osx-font-smoothing: auto;
98
101
  color: var(--ahsuite-label);
99
102
  isolation: isolate;
100
103
  visibility: visible;
@@ -388,6 +391,7 @@ span.ahsuite-row {
388
391
  Arial,
389
392
  sans-serif;
390
393
  -webkit-font-smoothing: auto;
394
+ -moz-osx-font-smoothing: auto;
391
395
  flex: 0 0 auto;
392
396
  }
393
397
 
@@ -466,6 +470,7 @@ span.ahsuite-row {
466
470
  Arial,
467
471
  sans-serif;
468
472
  -webkit-font-smoothing: auto;
473
+ -moz-osx-font-smoothing: auto;
469
474
  }
470
475
 
471
476
  .ahsuite-panel-head {
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { SUITE_NAV_CLICK_EVENT, suiteNavClickEvent } from './analytics.js';
1
2
  export { useNav } from './context.js';
2
3
  export { COLLAPSED_COOKIE } from './cookie.js';
3
4
  export { FALLBACK_CONFIG } from './fallback.js';
@@ -5,6 +6,7 @@ export { NavBar } from './nav-bar.js';
5
6
  export { NavTrigger } from './nav-trigger.js';
6
7
  export { NavProvider } from './provider.js';
7
8
  export { resolveApps } from './resolve.js';
9
+ export type { SuiteNavClickProperties } from './analytics.js';
8
10
  export type { NavContextValue } from './context.js';
9
11
  export type { NavBarProps } from './nav-bar.js';
10
12
  export type { NavTriggerProps } from './nav-trigger.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { SUITE_NAV_CLICK_EVENT, suiteNavClickEvent } from './analytics.js';
1
2
  export { useNav } from './context.js';
2
3
  export { COLLAPSED_COOKIE } from './cookie.js';
3
4
  export { FALLBACK_CONFIG } from './fallback.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artstorefronts/arthelper-nav",
3
- "version": "0.1.0-alpha.5",
3
+ "version": "0.1.0-alpha.7",
4
4
  "description": "The ArtHelper suite navigation bar — a config-driven, cross-origin app switcher.",
5
5
  "license": "ISC",
6
6
  "type": "module",