@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 +44 -29
- package/dist/analytics.d.ts +42 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +30 -0
- package/dist/analytics.js.map +1 -0
- package/dist/index.css +9 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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. **
|
|
71
|
-
analytics
|
|
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
|
-
> **
|
|
194
|
-
>
|
|
195
|
-
>
|
|
196
|
-
>
|
|
197
|
-
>
|
|
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
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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
|
-
|
|
330
|
-
|
|
331
|
-
}}
|
|
337
|
+
activeAppId="art-books"
|
|
338
|
+
onAppClick={(args) => amplitude.track(...suiteNavClickEvent(args, 'art_books'))}
|
|
332
339
|
>
|
|
333
340
|
```
|
|
334
341
|
|
|
335
|
-
|
|
336
|
-
`
|
|
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
|
-
*
|
|
81
|
-
* `antialiased` on its body thins the bar's text on macOS, so the same 600 weight
|
|
82
|
-
*
|
|
83
|
-
*
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
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