@syntrologie/adapt-nav 2.28.0 → 2.29.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/dist/NavWidgetLit.d.ts +7 -0
- package/dist/NavWidgetLit.d.ts.map +1 -1
- package/dist/cdn.d.ts +55 -0
- package/dist/cdn.d.ts.map +1 -0
- package/dist/cdn.js +33 -0
- package/dist/cdn.js.map +7 -0
- package/dist/chunk-VG3E3ALH.js +668 -0
- package/dist/chunk-VG3E3ALH.js.map +7 -0
- package/dist/{chunk-DDX6VH2W.js → chunk-XO4TLMHA.js} +183 -1
- package/dist/chunk-XO4TLMHA.js.map +7 -0
- package/dist/editor.d.ts +1 -2
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +32 -17
- package/dist/editor.js.map +2 -2
- package/dist/runtime.js +8 -629
- package/dist/runtime.js.map +4 -4
- package/dist/schema.d.ts +35 -5
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +1 -2
- package/dist/schema.js.map +1 -1
- package/package.json +5 -1
- package/dist/chunk-7DTOSQNC.js +0 -43
- package/dist/chunk-7DTOSQNC.js.map +0 -7
- package/dist/chunk-DDX6VH2W.js.map +0 -7
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__privateAdd,
|
|
3
|
+
__privateGet,
|
|
4
|
+
__privateMethod,
|
|
5
|
+
__privateSet,
|
|
6
|
+
normalizeRoute,
|
|
7
|
+
renderIcon,
|
|
8
|
+
routesMatch,
|
|
9
|
+
stripMountPlumbing
|
|
10
|
+
} from "./chunk-XO4TLMHA.js";
|
|
11
|
+
|
|
12
|
+
// src/NavWidgetLit.ts
|
|
13
|
+
import { html, LitElement, nothing } from "lit";
|
|
14
|
+
import { styleMap } from "lit/directives/style-map.js";
|
|
15
|
+
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
16
|
+
|
|
17
|
+
// src/resolveNavTarget.ts
|
|
18
|
+
function resolveNavTarget(args) {
|
|
19
|
+
const { href, external, windowOrigin, isIframe } = args;
|
|
20
|
+
const isOpaqueOrigin = windowOrigin === "null";
|
|
21
|
+
if (isIframe || isOpaqueOrigin) {
|
|
22
|
+
return { kind: "open", url: href };
|
|
23
|
+
}
|
|
24
|
+
if (external) {
|
|
25
|
+
return { kind: "open", url: href };
|
|
26
|
+
}
|
|
27
|
+
let url;
|
|
28
|
+
try {
|
|
29
|
+
url = new URL(href, windowOrigin);
|
|
30
|
+
} catch {
|
|
31
|
+
return { kind: "fullnav", url: href };
|
|
32
|
+
}
|
|
33
|
+
if (url.origin !== windowOrigin) {
|
|
34
|
+
return { kind: "fullnav", url: url.toString() };
|
|
35
|
+
}
|
|
36
|
+
return { kind: "spa", url };
|
|
37
|
+
}
|
|
38
|
+
function detectIsIframe() {
|
|
39
|
+
if (typeof window === "undefined") return false;
|
|
40
|
+
try {
|
|
41
|
+
return window !== window.top;
|
|
42
|
+
} catch {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/NavWidgetLit.ts
|
|
48
|
+
var TOKEN_PURPLE_4 = "#6a59ce";
|
|
49
|
+
var TOKEN_SLATE_GREY_7 = "#677384";
|
|
50
|
+
var TOKEN_SLATE_GREY_8 = "#87919f";
|
|
51
|
+
function escapeHtml(str) {
|
|
52
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
53
|
+
}
|
|
54
|
+
function renderIcon2(emoji) {
|
|
55
|
+
return renderIcon(emoji) || escapeHtml(emoji);
|
|
56
|
+
}
|
|
57
|
+
function routeMatchesCurrent(routes) {
|
|
58
|
+
if (typeof window === "undefined") return false;
|
|
59
|
+
let canonicalCurrent;
|
|
60
|
+
try {
|
|
61
|
+
canonicalCurrent = normalizeRoute(window.location.pathname);
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return routes.some((route) => {
|
|
66
|
+
if (route.endsWith("/**")) {
|
|
67
|
+
const prefix = route.slice(0, -3);
|
|
68
|
+
try {
|
|
69
|
+
const canonicalPrefix = prefix ? normalizeRoute(prefix) : "";
|
|
70
|
+
return canonicalCurrent.toLowerCase().startsWith(canonicalPrefix.toLowerCase());
|
|
71
|
+
} catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
return routesMatch(normalizeRoute(route), canonicalCurrent);
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function pulseElement(el) {
|
|
83
|
+
const keyframes = [
|
|
84
|
+
{ boxShadow: "0 0 0 0 rgba(13, 148, 136, 0.5)" },
|
|
85
|
+
{ boxShadow: "0 0 0 8px rgba(13, 148, 136, 0)" }
|
|
86
|
+
];
|
|
87
|
+
el.animate(keyframes, { duration: 600, iterations: 3, easing: "ease-out" });
|
|
88
|
+
}
|
|
89
|
+
function resolveTheme(theme) {
|
|
90
|
+
if (theme === "dark") return "dark";
|
|
91
|
+
if (theme === "light") return "light";
|
|
92
|
+
if (typeof window !== "undefined") {
|
|
93
|
+
return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
94
|
+
}
|
|
95
|
+
return "light";
|
|
96
|
+
}
|
|
97
|
+
var browserNavigationPort = {
|
|
98
|
+
open(url) {
|
|
99
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
100
|
+
},
|
|
101
|
+
fullNavigate(url) {
|
|
102
|
+
window.location.href = url;
|
|
103
|
+
},
|
|
104
|
+
pushState(url) {
|
|
105
|
+
window.history.pushState(null, "", url);
|
|
106
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var _contextUnsub, _accumulatorUnsub, _NavWidgetLit_instances, subscribeRuntime_fn, unsubscribeRuntime_fn, getVisibleTips_fn, getResolvedTheme_fn, handleToggle_fn, handleNavigate_fn, handleFocusAnchor_fn, publishEvent_fn, renderTipItem_fn;
|
|
110
|
+
var NavWidgetLit = class extends LitElement {
|
|
111
|
+
constructor() {
|
|
112
|
+
super(...arguments);
|
|
113
|
+
__privateAdd(this, _NavWidgetLit_instances);
|
|
114
|
+
// ---------- Public properties --------------------------------------------
|
|
115
|
+
this.config = { expandBehavior: "single", theme: "auto", actions: [] };
|
|
116
|
+
this.runtime = void 0;
|
|
117
|
+
this.instanceId = "nav-widget";
|
|
118
|
+
this.navigationPort = browserNavigationPort;
|
|
119
|
+
// ---------- Internal state -----------------------------------------------
|
|
120
|
+
/** @internal */
|
|
121
|
+
this._expandedIds = /* @__PURE__ */ new Set();
|
|
122
|
+
/** @internal */
|
|
123
|
+
this._renderTick = 0;
|
|
124
|
+
/** @internal */
|
|
125
|
+
this._hoveredId = null;
|
|
126
|
+
// ---------- Private subscriptions ----------------------------------------
|
|
127
|
+
__privateAdd(this, _contextUnsub, null);
|
|
128
|
+
__privateAdd(this, _accumulatorUnsub, null);
|
|
129
|
+
}
|
|
130
|
+
// ---------- No shadow DOM — inherit host CSS variables --------------------
|
|
131
|
+
createRenderRoot() {
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
// ---------- Lifecycle: connectedCallback ---------------------------------
|
|
135
|
+
connectedCallback() {
|
|
136
|
+
super.connectedCallback();
|
|
137
|
+
__privateMethod(this, _NavWidgetLit_instances, subscribeRuntime_fn).call(this);
|
|
138
|
+
}
|
|
139
|
+
// ---------- Lifecycle: disconnectedCallback ------------------------------
|
|
140
|
+
disconnectedCallback() {
|
|
141
|
+
super.disconnectedCallback();
|
|
142
|
+
__privateMethod(this, _NavWidgetLit_instances, unsubscribeRuntime_fn).call(this);
|
|
143
|
+
}
|
|
144
|
+
// ---------- Lifecycle: updated -------------------------------------------
|
|
145
|
+
updated(changed) {
|
|
146
|
+
if (changed.has("runtime")) {
|
|
147
|
+
__privateMethod(this, _NavWidgetLit_instances, unsubscribeRuntime_fn).call(this);
|
|
148
|
+
__privateMethod(this, _NavWidgetLit_instances, subscribeRuntime_fn).call(this);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// ---------- Render --------------------------------------------------------
|
|
152
|
+
render() {
|
|
153
|
+
const visibleTips = __privateMethod(this, _NavWidgetLit_instances, getVisibleTips_fn).call(this);
|
|
154
|
+
const theme = __privateMethod(this, _NavWidgetLit_instances, getResolvedTheme_fn).call(this);
|
|
155
|
+
const containerStyle = styleMap({
|
|
156
|
+
fontFamily: "var(--sc-font-family, system-ui, -apple-system, sans-serif)",
|
|
157
|
+
maxWidth: "100%",
|
|
158
|
+
overflow: "hidden",
|
|
159
|
+
backgroundColor: "transparent",
|
|
160
|
+
color: "inherit"
|
|
161
|
+
});
|
|
162
|
+
const accordionStyle = styleMap({
|
|
163
|
+
display: "flex",
|
|
164
|
+
flexDirection: "column",
|
|
165
|
+
gap: "var(--sc-content-item-gap, 6px)"
|
|
166
|
+
});
|
|
167
|
+
const categoryHeaderStyle = styleMap({
|
|
168
|
+
fontSize: "var(--sc-content-category-font-size, 12px)",
|
|
169
|
+
fontWeight: "600",
|
|
170
|
+
textTransform: "uppercase",
|
|
171
|
+
letterSpacing: "0.05em",
|
|
172
|
+
padding: "var(--sc-content-category-padding, 8px 4px 4px 4px)",
|
|
173
|
+
color: theme === "dark" ? TOKEN_SLATE_GREY_8 : TOKEN_SLATE_GREY_7
|
|
174
|
+
});
|
|
175
|
+
const emptyStateStyle = styleMap({
|
|
176
|
+
fontSize: "13px",
|
|
177
|
+
padding: "16px",
|
|
178
|
+
textAlign: "center",
|
|
179
|
+
color: theme === "dark" ? TOKEN_SLATE_GREY_7 : TOKEN_SLATE_GREY_8
|
|
180
|
+
});
|
|
181
|
+
if (visibleTips.length === 0) {
|
|
182
|
+
return html`
|
|
183
|
+
<div
|
|
184
|
+
style=${containerStyle}
|
|
185
|
+
data-adaptive-id=${this.instanceId}
|
|
186
|
+
data-adaptive-type="adaptive-nav"
|
|
187
|
+
>
|
|
188
|
+
<div style=${emptyStateStyle}>
|
|
189
|
+
You're all set for now! We'll share helpful tips here when they're relevant to what
|
|
190
|
+
you're doing.
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
const categoryGroups = /* @__PURE__ */ new Map();
|
|
196
|
+
for (const tip of visibleTips) {
|
|
197
|
+
const cat = tip.config.category;
|
|
198
|
+
if (!categoryGroups.has(cat)) {
|
|
199
|
+
categoryGroups.set(cat, []);
|
|
200
|
+
}
|
|
201
|
+
categoryGroups.get(cat).push(tip);
|
|
202
|
+
}
|
|
203
|
+
const hasCategories = visibleTips.some((t) => t.config.category);
|
|
204
|
+
return html`
|
|
205
|
+
<div
|
|
206
|
+
style=${containerStyle}
|
|
207
|
+
data-adaptive-id=${this.instanceId}
|
|
208
|
+
data-adaptive-type="adaptive-nav"
|
|
209
|
+
>
|
|
210
|
+
<div style=${accordionStyle}>
|
|
211
|
+
${hasCategories ? Array.from(categoryGroups.entries()).map(
|
|
212
|
+
([category, items]) => html`
|
|
213
|
+
${category ? html`<div style=${categoryHeaderStyle} data-category-header=${category}>${category}</div>` : nothing}
|
|
214
|
+
${items.map((tip, idx) => __privateMethod(this, _NavWidgetLit_instances, renderTipItem_fn).call(this, tip, idx, items.length))}
|
|
215
|
+
`
|
|
216
|
+
) : visibleTips.map((tip, idx) => __privateMethod(this, _NavWidgetLit_instances, renderTipItem_fn).call(this, tip, idx, visibleTips.length))}
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
`;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
_contextUnsub = new WeakMap();
|
|
223
|
+
_accumulatorUnsub = new WeakMap();
|
|
224
|
+
_NavWidgetLit_instances = new WeakSet();
|
|
225
|
+
// ---------- Runtime subscriptions ----------------------------------------
|
|
226
|
+
subscribeRuntime_fn = function() {
|
|
227
|
+
if (!this.runtime) return;
|
|
228
|
+
__privateSet(this, _contextUnsub, this.runtime.context.subscribe(() => {
|
|
229
|
+
this._renderTick += 1;
|
|
230
|
+
}));
|
|
231
|
+
if (this.runtime.accumulator?.subscribe) {
|
|
232
|
+
__privateSet(this, _accumulatorUnsub, this.runtime.accumulator.subscribe(() => {
|
|
233
|
+
this._renderTick += 1;
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
unsubscribeRuntime_fn = function() {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
(_a = __privateGet(this, _contextUnsub)) == null ? void 0 : _a.call(this);
|
|
240
|
+
__privateSet(this, _contextUnsub, null);
|
|
241
|
+
(_b = __privateGet(this, _accumulatorUnsub)) == null ? void 0 : _b.call(this);
|
|
242
|
+
__privateSet(this, _accumulatorUnsub, null);
|
|
243
|
+
};
|
|
244
|
+
// ---------- Computed helpers (called on each render) ---------------------
|
|
245
|
+
getVisibleTips_fn = function() {
|
|
246
|
+
void this._renderTick;
|
|
247
|
+
if (!this.runtime) return this.config.actions;
|
|
248
|
+
return this.config.actions.filter((tip) => {
|
|
249
|
+
if (!tip.triggerWhen) return true;
|
|
250
|
+
try {
|
|
251
|
+
const result = this.runtime.evaluateSync(tip.triggerWhen);
|
|
252
|
+
return result.value;
|
|
253
|
+
} catch {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
getResolvedTheme_fn = function() {
|
|
259
|
+
return resolveTheme(this.config.theme);
|
|
260
|
+
};
|
|
261
|
+
// ---------- Event handlers -----------------------------------------------
|
|
262
|
+
handleToggle_fn = function(id) {
|
|
263
|
+
const wasExpanded = this._expandedIds.has(id);
|
|
264
|
+
let next;
|
|
265
|
+
if (this.config.expandBehavior === "single") {
|
|
266
|
+
for (const prevId of this._expandedIds) {
|
|
267
|
+
if (prevId !== id) {
|
|
268
|
+
__privateMethod(this, _NavWidgetLit_instances, publishEvent_fn).call(this, "nav:toggled", {
|
|
269
|
+
tipId: prevId,
|
|
270
|
+
expanded: false
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
next = wasExpanded ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([id]);
|
|
275
|
+
} else {
|
|
276
|
+
next = new Set(this._expandedIds);
|
|
277
|
+
if (wasExpanded) {
|
|
278
|
+
next.delete(id);
|
|
279
|
+
} else {
|
|
280
|
+
next.add(id);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
__privateMethod(this, _NavWidgetLit_instances, publishEvent_fn).call(this, "nav:toggled", {
|
|
284
|
+
tipId: id,
|
|
285
|
+
expanded: !wasExpanded
|
|
286
|
+
});
|
|
287
|
+
this._expandedIds = next;
|
|
288
|
+
};
|
|
289
|
+
handleNavigate_fn = function(href, external) {
|
|
290
|
+
const normalized = href.trim().toLowerCase();
|
|
291
|
+
if (normalized.startsWith("javascript:") || normalized.startsWith("data:")) return;
|
|
292
|
+
__privateMethod(this, _NavWidgetLit_instances, publishEvent_fn).call(this, "nav:tip_clicked", { href, external });
|
|
293
|
+
this.dispatchEvent(
|
|
294
|
+
new CustomEvent("nav-tip-clicked", {
|
|
295
|
+
bubbles: true,
|
|
296
|
+
detail: { href, external, instanceId: this.instanceId }
|
|
297
|
+
})
|
|
298
|
+
);
|
|
299
|
+
const target = resolveNavTarget({
|
|
300
|
+
href,
|
|
301
|
+
external,
|
|
302
|
+
windowOrigin: typeof window !== "undefined" ? window.location.origin : "",
|
|
303
|
+
isIframe: detectIsIframe()
|
|
304
|
+
});
|
|
305
|
+
if (target.kind === "open") {
|
|
306
|
+
this.navigationPort.open(target.url);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (target.kind === "fullnav") {
|
|
310
|
+
this.navigationPort.fullNavigate(target.url);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
target.url.search = window.location.search;
|
|
314
|
+
if (!navigateWithFrameworkRouter(target.url.toString())) {
|
|
315
|
+
this.navigationPort.pushState(target.url.toString());
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
handleFocusAnchor_fn = function(anchor) {
|
|
319
|
+
const el = document.querySelector(anchor.selector);
|
|
320
|
+
if (!(el instanceof HTMLElement)) return;
|
|
321
|
+
__privateMethod(this, _NavWidgetLit_instances, publishEvent_fn).call(this, "nav:tip_focused", {
|
|
322
|
+
selector: anchor.selector,
|
|
323
|
+
route: anchor.route
|
|
324
|
+
});
|
|
325
|
+
this.dispatchEvent(
|
|
326
|
+
new CustomEvent("nav-tip-focused", {
|
|
327
|
+
bubbles: true,
|
|
328
|
+
detail: { selector: anchor.selector, instanceId: this.instanceId }
|
|
329
|
+
})
|
|
330
|
+
);
|
|
331
|
+
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
332
|
+
pulseElement(el);
|
|
333
|
+
setTimeout(() => el.focus(), 400);
|
|
334
|
+
};
|
|
335
|
+
publishEvent_fn = function(name, props) {
|
|
336
|
+
this.runtime?.events.publish(name, {
|
|
337
|
+
instanceId: this.instanceId,
|
|
338
|
+
timestamp: Date.now(),
|
|
339
|
+
...props
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
// ---------- Tip item rendering -------------------------------------------
|
|
343
|
+
renderTipItem_fn = function(tip, index, total) {
|
|
344
|
+
const { id, title, description, href, icon, external, anchor, category: _cat } = tip.config;
|
|
345
|
+
const isExpanded = this._expandedIds.has(id);
|
|
346
|
+
const isLast = index === total - 1;
|
|
347
|
+
const isHovered = this._hoveredId === id;
|
|
348
|
+
const theme = __privateMethod(this, _NavWidgetLit_instances, getResolvedTheme_fn).call(this);
|
|
349
|
+
const effectiveHref = anchor ? Array.isArray(anchor.route) ? anchor.route[0] : anchor.route : href;
|
|
350
|
+
const isSamePage = anchor ? routeMatchesCurrent(Array.isArray(anchor.route) ? anchor.route : [anchor.route]) : effectiveHref ? routeMatchesCurrent([effectiveHref]) : false;
|
|
351
|
+
const hasSelector = anchor?.selector && anchor.selector !== "*";
|
|
352
|
+
const isFocusAction = isSamePage && hasSelector;
|
|
353
|
+
const hasAction = !!effectiveHref || isFocusAction;
|
|
354
|
+
const ctaLabel = isFocusAction ? "Focus \u2192" : external ? "Go \u2197" : "Go \u2192";
|
|
355
|
+
const itemStyle = styleMap({
|
|
356
|
+
borderRadius: "var(--sc-content-border-radius, 8px)",
|
|
357
|
+
overflow: "hidden",
|
|
358
|
+
transition: "box-shadow 0.2s ease",
|
|
359
|
+
backgroundColor: "var(--sc-content-background)",
|
|
360
|
+
border: "var(--sc-content-border)",
|
|
361
|
+
...isExpanded ? {
|
|
362
|
+
boxShadow: theme === "dark" ? "0 4px 12px rgba(0, 0, 0, 0.15)" : "0 4px 12px rgba(0, 0, 0, 0.08)"
|
|
363
|
+
} : {},
|
|
364
|
+
...!isLast ? { borderBottom: "var(--sc-content-item-divider, none)" } : {}
|
|
365
|
+
});
|
|
366
|
+
const headerStyle = styleMap({
|
|
367
|
+
display: "flex",
|
|
368
|
+
alignItems: "center",
|
|
369
|
+
gap: "8px",
|
|
370
|
+
width: "100%",
|
|
371
|
+
padding: "var(--sc-content-item-padding, 12px 16px)",
|
|
372
|
+
border: "none",
|
|
373
|
+
cursor: "pointer",
|
|
374
|
+
fontSize: "var(--sc-content-item-font-size, 15px)",
|
|
375
|
+
fontWeight: "500",
|
|
376
|
+
fontFamily: "inherit",
|
|
377
|
+
textAlign: "left",
|
|
378
|
+
transition: "background-color 0.15s ease",
|
|
379
|
+
backgroundColor: isHovered ? "var(--sc-content-background-hover)" : "transparent",
|
|
380
|
+
color: "var(--sc-content-text-color)"
|
|
381
|
+
});
|
|
382
|
+
const chevronStyle = styleMap({
|
|
383
|
+
fontSize: "20px",
|
|
384
|
+
transition: "transform 0.2s ease",
|
|
385
|
+
marginLeft: "auto",
|
|
386
|
+
flexShrink: "0",
|
|
387
|
+
color: "var(--sc-content-chevron-color, currentColor)",
|
|
388
|
+
transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
|
|
389
|
+
});
|
|
390
|
+
const bodyStyle = styleMap({
|
|
391
|
+
overflow: "hidden",
|
|
392
|
+
transition: "max-height 0.25s ease, padding-bottom 0.25s ease",
|
|
393
|
+
padding: "var(--sc-content-body-padding, 0 16px 12px 16px)",
|
|
394
|
+
color: "var(--sc-content-text-secondary-color)",
|
|
395
|
+
maxHeight: isExpanded ? "500px" : "0",
|
|
396
|
+
paddingBottom: isExpanded ? "16px" : "0"
|
|
397
|
+
});
|
|
398
|
+
const descriptionStyle = styleMap({
|
|
399
|
+
fontSize: "var(--sc-content-body-font-size, 14px)",
|
|
400
|
+
lineHeight: "1.5",
|
|
401
|
+
margin: "0"
|
|
402
|
+
});
|
|
403
|
+
const linkButtonStyle = styleMap({
|
|
404
|
+
display: "inline-flex",
|
|
405
|
+
alignItems: "center",
|
|
406
|
+
gap: "4px",
|
|
407
|
+
marginTop: "10px",
|
|
408
|
+
padding: "6px 12px",
|
|
409
|
+
borderRadius: "6px",
|
|
410
|
+
textDecoration: "none",
|
|
411
|
+
fontSize: "13px",
|
|
412
|
+
fontWeight: "500",
|
|
413
|
+
cursor: "pointer",
|
|
414
|
+
border: "none",
|
|
415
|
+
transition: "background-color 0.15s ease",
|
|
416
|
+
backgroundColor: `var(--sc-color-primary, ${TOKEN_PURPLE_4})`,
|
|
417
|
+
color: "#ffffff"
|
|
418
|
+
});
|
|
419
|
+
const iconStyle = styleMap({
|
|
420
|
+
fontSize: "16px",
|
|
421
|
+
flexShrink: "0"
|
|
422
|
+
});
|
|
423
|
+
const onLinkClick = (e) => {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
e.stopPropagation();
|
|
426
|
+
if (isFocusAction && anchor) {
|
|
427
|
+
__privateMethod(this, _NavWidgetLit_instances, handleFocusAnchor_fn).call(this, anchor);
|
|
428
|
+
} else if (effectiveHref) {
|
|
429
|
+
__privateMethod(this, _NavWidgetLit_instances, handleNavigate_fn).call(this, effectiveHref, external ?? false);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
return html`
|
|
433
|
+
<div
|
|
434
|
+
style=${itemStyle}
|
|
435
|
+
data-nav-tip-id=${id}
|
|
436
|
+
>
|
|
437
|
+
<button
|
|
438
|
+
type="button"
|
|
439
|
+
style=${headerStyle}
|
|
440
|
+
aria-expanded=${isExpanded}
|
|
441
|
+
@click=${() => __privateMethod(this, _NavWidgetLit_instances, handleToggle_fn).call(this, id)}
|
|
442
|
+
@mouseenter=${() => {
|
|
443
|
+
this._hoveredId = id;
|
|
444
|
+
}}
|
|
445
|
+
@mouseleave=${() => {
|
|
446
|
+
this._hoveredId = null;
|
|
447
|
+
}}
|
|
448
|
+
>
|
|
449
|
+
${icon ? html`<span style=${iconStyle}>${unsafeHTML(renderIcon2(icon))}</span>` : nothing}
|
|
450
|
+
<span>${title}</span>
|
|
451
|
+
<span style=${chevronStyle}>${"\u203A"}</span>
|
|
452
|
+
</button>
|
|
453
|
+
<div style=${bodyStyle} aria-hidden=${!isExpanded}>
|
|
454
|
+
<p style=${descriptionStyle}>${description}</p>
|
|
455
|
+
${hasAction ? html`
|
|
456
|
+
<a
|
|
457
|
+
href=${effectiveHref || "#"}
|
|
458
|
+
style=${linkButtonStyle}
|
|
459
|
+
target=${external ? "_blank" : nothing}
|
|
460
|
+
rel=${external ? "noopener noreferrer" : nothing}
|
|
461
|
+
@click=${onLinkClick}
|
|
462
|
+
>${ctaLabel}</a>
|
|
463
|
+
` : nothing}
|
|
464
|
+
</div>
|
|
465
|
+
</div>
|
|
466
|
+
`;
|
|
467
|
+
};
|
|
468
|
+
// ---------- Reactive properties (no decorators) --------------------------
|
|
469
|
+
NavWidgetLit.properties = {
|
|
470
|
+
// Public inputs
|
|
471
|
+
config: { attribute: false },
|
|
472
|
+
runtime: { attribute: false },
|
|
473
|
+
instanceId: { type: String },
|
|
474
|
+
// Internal reactive state
|
|
475
|
+
_expandedIds: { state: true },
|
|
476
|
+
_renderTick: { state: true },
|
|
477
|
+
_hoveredId: { state: true }
|
|
478
|
+
};
|
|
479
|
+
var TAG_NAME = "syntro-nav-tips";
|
|
480
|
+
function registerNavWidgetLit() {
|
|
481
|
+
if (typeof window === "undefined") return;
|
|
482
|
+
if (!customElements.get(TAG_NAME)) {
|
|
483
|
+
customElements.define(TAG_NAME, NavWidgetLit);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/runtime.ts
|
|
488
|
+
var executeScrollTo = async (action, context) => {
|
|
489
|
+
const anchorEl = context.resolveAnchor(action.anchorId);
|
|
490
|
+
if (!anchorEl) {
|
|
491
|
+
console.error(
|
|
492
|
+
`[adaptive-nav] Anchor not found for scrollTo, skipping: ${action.anchorId.selector}`
|
|
493
|
+
);
|
|
494
|
+
return { cleanup: () => {
|
|
495
|
+
} };
|
|
496
|
+
}
|
|
497
|
+
anchorEl.scrollIntoView({
|
|
498
|
+
behavior: action.behavior ?? "smooth",
|
|
499
|
+
block: action.block ?? "center",
|
|
500
|
+
inline: action.inline ?? "nearest"
|
|
501
|
+
});
|
|
502
|
+
context.publishEvent("action.applied", {
|
|
503
|
+
id: context.generateId(),
|
|
504
|
+
kind: "navigation:scrollTo",
|
|
505
|
+
anchorId: action.anchorId,
|
|
506
|
+
behavior: action.behavior ?? "smooth"
|
|
507
|
+
});
|
|
508
|
+
if (action.pulse !== false && typeof context.applyAction === "function") {
|
|
509
|
+
void context.applyAction({
|
|
510
|
+
kind: "overlays:pulse",
|
|
511
|
+
anchorId: action.anchorId
|
|
512
|
+
}).catch(() => {
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
cleanup: () => {
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
};
|
|
520
|
+
function navigateWithFrameworkRouter(url) {
|
|
521
|
+
if (typeof window === "undefined") return false;
|
|
522
|
+
const w = window;
|
|
523
|
+
try {
|
|
524
|
+
const nextRouter = w.next?.router;
|
|
525
|
+
if (nextRouter?.push) {
|
|
526
|
+
nextRouter.push(url);
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
} catch {
|
|
530
|
+
}
|
|
531
|
+
try {
|
|
532
|
+
if (w.$nuxt?.$router?.push) {
|
|
533
|
+
w.$nuxt.$router.push(url);
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
} catch {
|
|
537
|
+
}
|
|
538
|
+
if (w.ng || w.getAllAngularRootElements || document.querySelector("[ng-version]")) {
|
|
539
|
+
window.location.href = url;
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
if (w.__SVELTEKIT_DATA__ || document.body?.hasAttribute("data-sveltekit")) {
|
|
543
|
+
window.location.href = url;
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
if (document.querySelector("[data-astro-transition-fallback]")) {
|
|
547
|
+
window.location.href = url;
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
function isSameOrigin(url) {
|
|
553
|
+
try {
|
|
554
|
+
const parsed = new URL(url, window.location.origin);
|
|
555
|
+
return parsed.origin === window.location.origin;
|
|
556
|
+
} catch {
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
var executeNavigate = async (action, context) => {
|
|
561
|
+
const url = action.url.trim();
|
|
562
|
+
if (url.toLowerCase().startsWith("javascript:")) {
|
|
563
|
+
throw new Error("javascript: URLs are not allowed");
|
|
564
|
+
}
|
|
565
|
+
const target = action.target ?? "_self";
|
|
566
|
+
context.publishEvent("action.applied", {
|
|
567
|
+
id: context.generateId(),
|
|
568
|
+
kind: "navigation:navigate",
|
|
569
|
+
url: action.url,
|
|
570
|
+
target
|
|
571
|
+
});
|
|
572
|
+
if (target === "_blank") {
|
|
573
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
574
|
+
} else if (!action.forceFullNavigation && isSameOrigin(url)) {
|
|
575
|
+
if (!navigateWithFrameworkRouter(url)) {
|
|
576
|
+
window.history.pushState(null, "", url);
|
|
577
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
578
|
+
}
|
|
579
|
+
} else {
|
|
580
|
+
window.location.href = url;
|
|
581
|
+
}
|
|
582
|
+
return {
|
|
583
|
+
cleanup: () => {
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
};
|
|
587
|
+
var DEFAULT_NAV_CONFIG = {
|
|
588
|
+
expandBehavior: "single",
|
|
589
|
+
theme: "auto",
|
|
590
|
+
actions: []
|
|
591
|
+
};
|
|
592
|
+
var NavWidgetLitMountable = {
|
|
593
|
+
mount(container, config) {
|
|
594
|
+
registerNavWidgetLit();
|
|
595
|
+
const el = document.createElement("syntro-nav-tips");
|
|
596
|
+
const incoming = config ?? null;
|
|
597
|
+
const stripped = stripMountPlumbing(incoming);
|
|
598
|
+
const runtime2 = incoming?.runtime;
|
|
599
|
+
const instanceId = incoming?.instanceId ?? "nav-widget";
|
|
600
|
+
const navConfig = incoming ? stripped : { ...DEFAULT_NAV_CONFIG };
|
|
601
|
+
Object.assign(el, {
|
|
602
|
+
config: navConfig,
|
|
603
|
+
runtime: runtime2,
|
|
604
|
+
instanceId
|
|
605
|
+
});
|
|
606
|
+
container.appendChild(el);
|
|
607
|
+
return () => el.remove();
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
var executors = [
|
|
611
|
+
{ kind: "navigation:scrollTo", executor: executeScrollTo },
|
|
612
|
+
{ kind: "navigation:navigate", executor: executeNavigate }
|
|
613
|
+
];
|
|
614
|
+
var runtime = {
|
|
615
|
+
id: "adaptive-nav",
|
|
616
|
+
version: "2.0.0",
|
|
617
|
+
name: "Navigation Tips",
|
|
618
|
+
description: "Navigation actions and accordion-based tips with per-item conditional visibility",
|
|
619
|
+
/**
|
|
620
|
+
* Navigation action executors (scrollTo, navigate).
|
|
621
|
+
*/
|
|
622
|
+
executors,
|
|
623
|
+
/**
|
|
624
|
+
* Widget definitions for the runtime's WidgetRegistry.
|
|
625
|
+
*/
|
|
626
|
+
widgets: [
|
|
627
|
+
{
|
|
628
|
+
id: "adaptive-nav:tips",
|
|
629
|
+
component: NavWidgetLitMountable,
|
|
630
|
+
metadata: {
|
|
631
|
+
name: "Navigation Tips",
|
|
632
|
+
description: "Accordion of contextual navigation tips with per-item visibility",
|
|
633
|
+
icon: "\u{1F9ED}"
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
],
|
|
637
|
+
/**
|
|
638
|
+
* Extract notify watcher entries from tile config props.
|
|
639
|
+
* The runtime evaluates these continuously (even with drawer closed)
|
|
640
|
+
* and publishes nav:tip_revealed when triggerWhen transitions false → true.
|
|
641
|
+
*/
|
|
642
|
+
notifyWatchers(props) {
|
|
643
|
+
const actions = props.actions ?? [];
|
|
644
|
+
return actions.filter((a) => a.notify && a.triggerWhen).map((a) => ({
|
|
645
|
+
id: `nav:${a.config.id}`,
|
|
646
|
+
strategy: a.triggerWhen,
|
|
647
|
+
eventName: "nav:tip_revealed",
|
|
648
|
+
eventProps: {
|
|
649
|
+
tipId: a.config.id,
|
|
650
|
+
title: a.notify.title,
|
|
651
|
+
body: a.notify.body,
|
|
652
|
+
icon: a.notify.icon
|
|
653
|
+
}
|
|
654
|
+
}));
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
var runtime_default = runtime;
|
|
658
|
+
|
|
659
|
+
export {
|
|
660
|
+
executeScrollTo,
|
|
661
|
+
navigateWithFrameworkRouter,
|
|
662
|
+
executeNavigate,
|
|
663
|
+
NavWidgetLitMountable,
|
|
664
|
+
executors,
|
|
665
|
+
runtime,
|
|
666
|
+
runtime_default
|
|
667
|
+
};
|
|
668
|
+
//# sourceMappingURL=chunk-VG3E3ALH.js.map
|