@syntrologie/adapt-nav 2.14.0 → 2.15.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 +56 -0
- package/dist/NavWidgetLit.d.ts.map +1 -0
- package/dist/NavWidgetLit.js +495 -0
- package/dist/NavWidgetLit.test.d.ts +8 -0
- package/dist/NavWidgetLit.test.d.ts.map +1 -0
- package/dist/NavWidgetLit.test.js +199 -0
- package/dist/editor-lit.d.ts +49 -0
- package/dist/editor-lit.d.ts.map +1 -0
- package/dist/editor-lit.js +319 -0
- package/dist/runtime-lit.d.ts +108 -0
- package/dist/runtime-lit.d.ts.map +1 -0
- package/dist/runtime-lit.js +241 -0
- package/dist/runtime.d.ts +15 -3
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +29 -0
- package/dist/schema.d.ts +84 -84
- package/dist/schema.d.ts.map +1 -1
- package/node_modules/@syntro/design-system/dist/tokens/index.d.ts +2 -0
- package/node_modules/@syntro/design-system/dist/tokens/index.d.ts.map +1 -1
- package/node_modules/@syntro/design-system/dist/tokens/index.js +2 -0
- package/node_modules/@syntro/design-system/dist/tokens/panel-shell.d.ts +93 -0
- package/node_modules/@syntro/design-system/dist/tokens/panel-shell.d.ts.map +1 -0
- package/node_modules/@syntro/design-system/dist/tokens/panel-shell.js +72 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPickerLit.d.ts +84 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPickerLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPickerLit.js +323 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggleLit.d.ts +25 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggleLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggleLit.js +55 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLineLit.d.ts +33 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLineLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLineLit.js +118 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadgeLit.d.ts +32 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadgeLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadgeLit.js +68 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSectionLit.d.ts +34 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSectionLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSectionLit.js +57 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButtonLit.d.ts +13 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButtonLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButtonLit.js +31 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBodyLit.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBodyLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBodyLit.js +15 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCardLit.d.ts +36 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCardLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCardLit.js +102 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooterLit.d.ts +20 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooterLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooterLit.js +48 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeaderLit.d.ts +16 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeaderLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeaderLit.js +25 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInputLit.d.ts +66 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInputLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInputLit.js +87 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayoutLit.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayoutLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayoutLit.js +15 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts.map +1 -1
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.js +28 -17
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShellLit.d.ts +66 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShellLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShellLit.js +528 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelectLit.d.ts +41 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelectLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelectLit.js +63 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextareaLit.d.ts +55 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextareaLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextareaLit.js +92 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlightLit.d.ts +90 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlightLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlightLit.js +242 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyStateLit.d.ts +12 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyStateLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyStateLit.js +21 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeaderLit.d.ts +21 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeaderLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeaderLit.js +33 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourneyLit.d.ts +28 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourneyLit.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourneyLit.js +121 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/controllers/PanelShellController.d.ts +110 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/controllers/PanelShellController.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/controllers/PanelShellController.js +476 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts.map +1 -1
- package/node_modules/@syntrologie/shared-editor-ui/dist/index.js +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/lit-elements.d.ts +15 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/lit-elements.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/lit-elements.js +14 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts +0 -4
- package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts.map +1 -1
- package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.js +17 -1
- package/node_modules/@syntrologie/shared-editor-ui/package.json +9 -1
- package/package.json +12 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NavWidgetLit — Vitest + @open-wc/testing-helpers unit tests
|
|
3
|
+
*
|
|
4
|
+
* Tests cover: rendering, expand/collapse, nav-tip-clicked event, XSS rejection,
|
|
5
|
+
* empty state, category grouping, and visibility filtering (triggerWhen).
|
|
6
|
+
*/
|
|
7
|
+
import { fixture, html } from '@open-wc/testing-helpers';
|
|
8
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
9
|
+
import { NavWidgetLit } from './NavWidgetLit';
|
|
10
|
+
// ── Custom element registration ───────────────────────────────────────────────
|
|
11
|
+
const TAG = 'syntro-nav-tips';
|
|
12
|
+
if (!customElements.get(TAG)) {
|
|
13
|
+
customElements.define(TAG, NavWidgetLit);
|
|
14
|
+
}
|
|
15
|
+
// ── Helpers ────────────────────────────────────────────────────────────────────
|
|
16
|
+
function makeTip(id, overrides = {}) {
|
|
17
|
+
return {
|
|
18
|
+
kind: 'nav:tip',
|
|
19
|
+
config: {
|
|
20
|
+
id,
|
|
21
|
+
title: `Tip ${id}`,
|
|
22
|
+
description: `Description for tip ${id}`,
|
|
23
|
+
...overrides,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function makeRuntime(overrides = {}) {
|
|
28
|
+
return {
|
|
29
|
+
evaluateSync: vi.fn().mockReturnValue({ value: true, isFallback: false }),
|
|
30
|
+
context: { subscribe: vi.fn().mockReturnValue(vi.fn()) },
|
|
31
|
+
events: { publish: vi.fn() },
|
|
32
|
+
accumulator: {
|
|
33
|
+
subscribe: vi.fn().mockReturnValue(vi.fn()),
|
|
34
|
+
register: vi.fn(),
|
|
35
|
+
},
|
|
36
|
+
...overrides,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function makeConfig(tips, overrides = {}) {
|
|
40
|
+
return {
|
|
41
|
+
expandBehavior: 'single',
|
|
42
|
+
theme: 'light',
|
|
43
|
+
actions: tips,
|
|
44
|
+
...overrides,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function renderWidget(tips, configOverrides = {}, runtime) {
|
|
48
|
+
const el = await fixture(html `<syntro-nav-tips></syntro-nav-tips>`);
|
|
49
|
+
el.config = makeConfig(tips, configOverrides);
|
|
50
|
+
el.runtime = runtime;
|
|
51
|
+
await el.updateComplete;
|
|
52
|
+
return el;
|
|
53
|
+
}
|
|
54
|
+
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
55
|
+
describe('NavWidgetLit', () => {
|
|
56
|
+
// ── Rendering ────────────────────────────────────────────────────────────
|
|
57
|
+
it('renders navigation tips from config', async () => {
|
|
58
|
+
const el = await renderWidget([makeTip('t1'), makeTip('t2')]);
|
|
59
|
+
expect(el.querySelectorAll('[data-nav-tip-id]')).toHaveLength(2);
|
|
60
|
+
expect(el.querySelector('[data-nav-tip-id="t1"]')).not.toBeNull();
|
|
61
|
+
expect(el.querySelector('[data-nav-tip-id="t2"]')).not.toBeNull();
|
|
62
|
+
});
|
|
63
|
+
it('renders tip titles in button text', async () => {
|
|
64
|
+
const el = await renderWidget([makeTip('a', { title: 'My Nav Tip' })]);
|
|
65
|
+
const btn = el.querySelector('button');
|
|
66
|
+
expect(btn.textContent).toContain('My Nav Tip');
|
|
67
|
+
});
|
|
68
|
+
// ── Expand / collapse ────────────────────────────────────────────────────
|
|
69
|
+
it('starts with all tips collapsed', async () => {
|
|
70
|
+
const el = await renderWidget([makeTip('t1'), makeTip('t2')]);
|
|
71
|
+
const buttons = el.querySelectorAll('button[aria-expanded]');
|
|
72
|
+
for (const btn of Array.from(buttons)) {
|
|
73
|
+
expect(btn.getAttribute('aria-expanded')).toBe('false');
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
it('expands a tip when its header button is clicked', async () => {
|
|
77
|
+
const el = await renderWidget([makeTip('t1')]);
|
|
78
|
+
const btn = el.querySelector('[data-nav-tip-id="t1"] button');
|
|
79
|
+
btn.click();
|
|
80
|
+
await el.updateComplete;
|
|
81
|
+
expect(btn.getAttribute('aria-expanded')).toBe('true');
|
|
82
|
+
});
|
|
83
|
+
it('collapses an expanded tip on second click', async () => {
|
|
84
|
+
const el = await renderWidget([makeTip('t1')]);
|
|
85
|
+
const btn = el.querySelector('[data-nav-tip-id="t1"] button');
|
|
86
|
+
btn.click();
|
|
87
|
+
await el.updateComplete;
|
|
88
|
+
btn.click();
|
|
89
|
+
await el.updateComplete;
|
|
90
|
+
expect(btn.getAttribute('aria-expanded')).toBe('false');
|
|
91
|
+
});
|
|
92
|
+
it('collapses previously-expanded tip in single-expand mode', async () => {
|
|
93
|
+
const el = await renderWidget([makeTip('t1'), makeTip('t2')], {
|
|
94
|
+
expandBehavior: 'single',
|
|
95
|
+
});
|
|
96
|
+
const btn1 = el.querySelector('[data-nav-tip-id="t1"] button');
|
|
97
|
+
const btn2 = el.querySelector('[data-nav-tip-id="t2"] button');
|
|
98
|
+
btn1.click();
|
|
99
|
+
await el.updateComplete;
|
|
100
|
+
expect(btn1.getAttribute('aria-expanded')).toBe('true');
|
|
101
|
+
btn2.click();
|
|
102
|
+
await el.updateComplete;
|
|
103
|
+
expect(btn1.getAttribute('aria-expanded')).toBe('false');
|
|
104
|
+
expect(btn2.getAttribute('aria-expanded')).toBe('true');
|
|
105
|
+
});
|
|
106
|
+
it('allows multiple tips open simultaneously in multiple-expand mode', async () => {
|
|
107
|
+
const el = await renderWidget([makeTip('t1'), makeTip('t2')], {
|
|
108
|
+
expandBehavior: 'multiple',
|
|
109
|
+
});
|
|
110
|
+
const btn1 = el.querySelector('[data-nav-tip-id="t1"] button');
|
|
111
|
+
const btn2 = el.querySelector('[data-nav-tip-id="t2"] button');
|
|
112
|
+
btn1.click();
|
|
113
|
+
await el.updateComplete;
|
|
114
|
+
btn2.click();
|
|
115
|
+
await el.updateComplete;
|
|
116
|
+
expect(btn1.getAttribute('aria-expanded')).toBe('true');
|
|
117
|
+
expect(btn2.getAttribute('aria-expanded')).toBe('true');
|
|
118
|
+
});
|
|
119
|
+
// ── Custom event ─────────────────────────────────────────────────────────
|
|
120
|
+
it('fires nav-tip-clicked custom event when CTA link is clicked', async () => {
|
|
121
|
+
const tip = makeTip('t1', { href: '/dashboard' });
|
|
122
|
+
const el = await renderWidget([tip]);
|
|
123
|
+
// Expand so the CTA link is rendered
|
|
124
|
+
const btn = el.querySelector('[data-nav-tip-id="t1"] button');
|
|
125
|
+
btn.click();
|
|
126
|
+
await el.updateComplete;
|
|
127
|
+
const events = [];
|
|
128
|
+
el.addEventListener('nav-tip-clicked', (e) => events.push(e));
|
|
129
|
+
const link = el.querySelector('a');
|
|
130
|
+
link.click();
|
|
131
|
+
expect(events).toHaveLength(1);
|
|
132
|
+
expect(events[0].detail.href).toBe('/dashboard');
|
|
133
|
+
});
|
|
134
|
+
// ── XSS rejection ────────────────────────────────────────────────────────
|
|
135
|
+
it('does not navigate when href starts with javascript:', async () => {
|
|
136
|
+
const originalOpen = window.open;
|
|
137
|
+
const openSpy = vi.fn();
|
|
138
|
+
window.open = openSpy;
|
|
139
|
+
// Directly invoke the internal navigate path via a link with a JS URL
|
|
140
|
+
const tip = makeTip('xss', { href: 'javascript:alert(1)', external: false });
|
|
141
|
+
const el = await renderWidget([tip]);
|
|
142
|
+
const headerBtn = el.querySelector('[data-nav-tip-id="xss"] button');
|
|
143
|
+
headerBtn.click();
|
|
144
|
+
await el.updateComplete;
|
|
145
|
+
const link = el.querySelector('a');
|
|
146
|
+
if (link) {
|
|
147
|
+
const navEvents = [];
|
|
148
|
+
el.addEventListener('nav-tip-clicked', (e) => navEvents.push(e));
|
|
149
|
+
link.click();
|
|
150
|
+
// The click handler checks the href and bails out early — no event should fire
|
|
151
|
+
expect(navEvents).toHaveLength(0);
|
|
152
|
+
}
|
|
153
|
+
window.open = originalOpen;
|
|
154
|
+
});
|
|
155
|
+
// ── Empty state ───────────────────────────────────────────────────────────
|
|
156
|
+
it('renders empty state when config has no actions', async () => {
|
|
157
|
+
const el = await renderWidget([]);
|
|
158
|
+
// No tip items
|
|
159
|
+
expect(el.querySelectorAll('[data-nav-tip-id]')).toHaveLength(0);
|
|
160
|
+
// The empty-state message is present
|
|
161
|
+
expect(el.textContent).toContain("You're all set for now");
|
|
162
|
+
});
|
|
163
|
+
// ── Category grouping ─────────────────────────────────────────────────────
|
|
164
|
+
it('renders category headers when tips have categories', async () => {
|
|
165
|
+
const tips = [
|
|
166
|
+
makeTip('t1', { category: 'Getting Started' }),
|
|
167
|
+
makeTip('t2', { category: 'Advanced' }),
|
|
168
|
+
];
|
|
169
|
+
const el = await renderWidget(tips);
|
|
170
|
+
const catHeaders = el.querySelectorAll('[data-category-header]');
|
|
171
|
+
expect(catHeaders).toHaveLength(2);
|
|
172
|
+
const headerTexts = Array.from(catHeaders).map((h) => h.textContent?.trim());
|
|
173
|
+
expect(headerTexts).toContain('Getting Started');
|
|
174
|
+
expect(headerTexts).toContain('Advanced');
|
|
175
|
+
});
|
|
176
|
+
it('does not render category headers when no tips have categories', async () => {
|
|
177
|
+
const tips = [makeTip('t1'), makeTip('t2')];
|
|
178
|
+
const el = await renderWidget(tips);
|
|
179
|
+
expect(el.querySelectorAll('[data-category-header]')).toHaveLength(0);
|
|
180
|
+
});
|
|
181
|
+
// ── Visibility filtering (triggerWhen) ────────────────────────────────────
|
|
182
|
+
it('hides tips whose triggerWhen evaluates to false', async () => {
|
|
183
|
+
const visibleTip = makeTip('visible');
|
|
184
|
+
const hiddenTip = {
|
|
185
|
+
...makeTip('hidden'),
|
|
186
|
+
triggerWhen: { type: 'rules', rules: [], default: false },
|
|
187
|
+
};
|
|
188
|
+
const runtime = makeRuntime({
|
|
189
|
+
evaluateSync: vi.fn((strategy) => {
|
|
190
|
+
if (strategy.default === false)
|
|
191
|
+
return { value: false, isFallback: false };
|
|
192
|
+
return { value: true, isFallback: false };
|
|
193
|
+
}),
|
|
194
|
+
});
|
|
195
|
+
const el = await renderWidget([visibleTip, hiddenTip], {}, runtime);
|
|
196
|
+
expect(el.querySelector('[data-nav-tip-id="visible"]')).not.toBeNull();
|
|
197
|
+
expect(el.querySelector('[data-nav-tip-id="hidden"]')).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Nav - Lit Editor Component
|
|
3
|
+
*
|
|
4
|
+
* Lit web component port of the React Nav editor (editor.tsx).
|
|
5
|
+
* Displays nav tip cards with detection badges, inline editing
|
|
6
|
+
* (Title, Description, Link URL, Icon, Category), and rationale.
|
|
7
|
+
*
|
|
8
|
+
* Custom events:
|
|
9
|
+
* navigate-home — user clicked back
|
|
10
|
+
* dirty-change — { dirty: boolean }
|
|
11
|
+
*/
|
|
12
|
+
import { LitElement } from 'lit';
|
|
13
|
+
import { type NavConfig } from './types';
|
|
14
|
+
export declare class NavEditorLit extends LitElement {
|
|
15
|
+
static properties: {
|
|
16
|
+
config: {
|
|
17
|
+
attribute: boolean;
|
|
18
|
+
};
|
|
19
|
+
onChange: {
|
|
20
|
+
attribute: boolean;
|
|
21
|
+
};
|
|
22
|
+
_editingKey: {
|
|
23
|
+
state: boolean;
|
|
24
|
+
};
|
|
25
|
+
_detectionMap: {
|
|
26
|
+
state: boolean;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
config: NavConfig | null;
|
|
30
|
+
onChange: ((updated: Record<string, unknown>) => void) | null;
|
|
31
|
+
private _editingKey;
|
|
32
|
+
private _detectionMap;
|
|
33
|
+
private _detectionInterval;
|
|
34
|
+
private _onPopstate;
|
|
35
|
+
createRenderRoot(): this;
|
|
36
|
+
connectedCallback(): void;
|
|
37
|
+
disconnectedCallback(): void;
|
|
38
|
+
firstUpdated(): void;
|
|
39
|
+
private _runDetection;
|
|
40
|
+
private _handleBack;
|
|
41
|
+
private _handleItemClick;
|
|
42
|
+
private _handleFieldChange;
|
|
43
|
+
private _handleBadgeClick;
|
|
44
|
+
private _renderDetectionBadge;
|
|
45
|
+
private _renderEditMode;
|
|
46
|
+
private _renderListMode;
|
|
47
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=editor-lit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-lit.d.ts","sourceRoot":"","sources":["../src/editor-lit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAQ,UAAU,EAAW,MAAM,KAAK,CAAC;AAGhD,OAAO,EAAe,KAAK,SAAS,EAAwC,MAAM,SAAS,CAAC;AAkH5F,qBAAa,YAAa,SAAQ,UAAU;IAC1C,OAAgB,UAAU;;;;;;;;;;;;;MAKxB;IAEF,MAAM,EAAE,SAAS,GAAG,IAAI,CAAQ;IAChC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAErE,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,kBAAkB,CAA+C;IACzE,OAAO,CAAC,WAAW,CAA8B;IAExC,gBAAgB;IAIhB,iBAAiB,IAAI,IAAI;IAOzB,oBAAoB,IAAI,IAAI;IAS5B,YAAY,IAAI,IAAI;IAK7B,OAAO,CAAC,aAAa,CAGnB;IAIF,OAAO,CAAC,WAAW,CAMjB;IAEF,OAAO,CAAC,gBAAgB,CAEtB;IAEF,OAAO,CAAC,kBAAkB,CAaxB;IAIF,OAAO,CAAC,iBAAiB,CAOvB;IAEF,OAAO,CAAC,qBAAqB,CAkB3B;IAEF,OAAO,CAAC,eAAe,CA0DrB;IAEF,OAAO,CAAC,eAAe,CA0CrB;IAEO,MAAM;CAoChB"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Nav - Lit Editor Component
|
|
3
|
+
*
|
|
4
|
+
* Lit web component port of the React Nav editor (editor.tsx).
|
|
5
|
+
* Displays nav tip cards with detection badges, inline editing
|
|
6
|
+
* (Title, Description, Link URL, Icon, Category), and rationale.
|
|
7
|
+
*
|
|
8
|
+
* Custom events:
|
|
9
|
+
* navigate-home — user clicked back
|
|
10
|
+
* dirty-change — { dirty: boolean }
|
|
11
|
+
*/
|
|
12
|
+
import { html, LitElement, nothing } from 'lit';
|
|
13
|
+
import { describeTrigger, summarizeNavItem } from './summarize';
|
|
14
|
+
import { isOwnAction } from './types';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Targeting Extraction
|
|
17
|
+
// ============================================================================
|
|
18
|
+
const isRuleStrategy = (s) => typeof s === 'object' &&
|
|
19
|
+
s !== null &&
|
|
20
|
+
s.type === 'rules' &&
|
|
21
|
+
Array.isArray(s.rules);
|
|
22
|
+
const extractFirstPage = (triggerWhen) => {
|
|
23
|
+
if (!triggerWhen || !isRuleStrategy(triggerWhen))
|
|
24
|
+
return null;
|
|
25
|
+
for (const rule of triggerWhen.rules) {
|
|
26
|
+
for (const cond of rule.conditions) {
|
|
27
|
+
const c = cond;
|
|
28
|
+
if (c.type === 'page_url' && typeof c.url === 'string')
|
|
29
|
+
return c.url;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
const extractFirstAnchor = (triggerWhen) => {
|
|
35
|
+
if (!triggerWhen || !isRuleStrategy(triggerWhen))
|
|
36
|
+
return null;
|
|
37
|
+
for (const rule of triggerWhen.rules) {
|
|
38
|
+
for (const cond of rule.conditions) {
|
|
39
|
+
const c = cond;
|
|
40
|
+
if (c.type === 'anchor_visible' && typeof c.anchorId === 'string')
|
|
41
|
+
return c.anchorId;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Helpers
|
|
48
|
+
// ============================================================================
|
|
49
|
+
const flattenItems = (config) => {
|
|
50
|
+
const actions = (config.actions || []).filter(isOwnAction);
|
|
51
|
+
return actions.map((tip, i) => {
|
|
52
|
+
// Prefer the tip's own anchor (real pipeline data ships the target here).
|
|
53
|
+
// Fall back to an `anchor_visible` condition inside triggerWhen for older configs.
|
|
54
|
+
const tipAnchor = tip.kind === 'nav:tip' ? tip.config.anchor?.selector : undefined;
|
|
55
|
+
const rawRoute = tip.kind === 'nav:tip' ? tip.config.anchor?.route : undefined;
|
|
56
|
+
const tipRoute = typeof rawRoute === 'string' ? rawRoute : undefined;
|
|
57
|
+
return {
|
|
58
|
+
key: String(i),
|
|
59
|
+
index: i,
|
|
60
|
+
summary: summarizeNavItem(tip),
|
|
61
|
+
trigger: describeTrigger(tip.triggerWhen),
|
|
62
|
+
rationale: tip.rationale?.why,
|
|
63
|
+
firstAnchor: tipAnchor || extractFirstAnchor(tip.triggerWhen),
|
|
64
|
+
firstPage: tipRoute || extractFirstPage(tip.triggerWhen),
|
|
65
|
+
tip,
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
const runDetection = (items) => {
|
|
70
|
+
const map = new Map();
|
|
71
|
+
const currentPath = window.location.pathname;
|
|
72
|
+
for (const item of items) {
|
|
73
|
+
// Page match
|
|
74
|
+
let pageMatch = true;
|
|
75
|
+
if (item.firstPage) {
|
|
76
|
+
const pattern = item.firstPage;
|
|
77
|
+
const regex = new RegExp(`^${pattern.replace(/\*\*/g, '.*').replace(/(?<!\.)(\*)/g, '[^/]*')}$`);
|
|
78
|
+
pageMatch = regex.test(currentPath);
|
|
79
|
+
}
|
|
80
|
+
// Anchor match
|
|
81
|
+
let anchorFound = false;
|
|
82
|
+
if (item.firstAnchor) {
|
|
83
|
+
try {
|
|
84
|
+
anchorFound = document.querySelector(item.firstAnchor) !== null;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Invalid selector
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
anchorFound = pageMatch;
|
|
92
|
+
}
|
|
93
|
+
map.set(item.key, { found: pageMatch && anchorFound });
|
|
94
|
+
}
|
|
95
|
+
return map;
|
|
96
|
+
};
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// Element
|
|
99
|
+
// ============================================================================
|
|
100
|
+
export class NavEditorLit extends LitElement {
|
|
101
|
+
constructor() {
|
|
102
|
+
super(...arguments);
|
|
103
|
+
this.config = null;
|
|
104
|
+
this.onChange = null;
|
|
105
|
+
this._editingKey = null;
|
|
106
|
+
this._detectionMap = new Map();
|
|
107
|
+
this._detectionInterval = null;
|
|
108
|
+
this._onPopstate = () => this._runDetection();
|
|
109
|
+
this._runDetection = () => {
|
|
110
|
+
if (!this.config)
|
|
111
|
+
return;
|
|
112
|
+
this._detectionMap = runDetection(flattenItems(this.config));
|
|
113
|
+
};
|
|
114
|
+
// ---- Actions ----
|
|
115
|
+
this._handleBack = () => {
|
|
116
|
+
if (this._editingKey !== null) {
|
|
117
|
+
this._editingKey = null;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.dispatchEvent(new CustomEvent('navigate-home', { bubbles: true }));
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
this._handleItemClick = (key) => {
|
|
124
|
+
this._editingKey = key;
|
|
125
|
+
};
|
|
126
|
+
this._handleFieldChange = (index, field, value) => {
|
|
127
|
+
if (!this.config || !this.onChange)
|
|
128
|
+
return;
|
|
129
|
+
const ownActions = (this.config.actions || []).filter(isOwnAction).slice();
|
|
130
|
+
const tip = { ...ownActions[index], config: { ...ownActions[index].config } };
|
|
131
|
+
tip.config[field] = value;
|
|
132
|
+
ownActions[index] = tip;
|
|
133
|
+
const otherActions = (this.config.actions || []).filter((a) => !isOwnAction(a));
|
|
134
|
+
const updated = { ...this.config, actions: [...otherActions, ...ownActions] };
|
|
135
|
+
this.onChange(updated);
|
|
136
|
+
this.dispatchEvent(new CustomEvent('dirty-change', { detail: { dirty: true }, bubbles: true }));
|
|
137
|
+
};
|
|
138
|
+
// ---- Render ----
|
|
139
|
+
this._handleBadgeClick = (item, e) => {
|
|
140
|
+
e.stopPropagation();
|
|
141
|
+
const href = item.tip.config.href;
|
|
142
|
+
if (!href)
|
|
143
|
+
return;
|
|
144
|
+
// SPA navigate via pushState + popstate
|
|
145
|
+
window.history.pushState({}, '', href);
|
|
146
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
147
|
+
};
|
|
148
|
+
this._renderDetectionBadge = (item) => {
|
|
149
|
+
const detection = this._detectionMap.get(item.key);
|
|
150
|
+
const found = detection?.found ?? false;
|
|
151
|
+
if (found) {
|
|
152
|
+
return html `<button type="button"
|
|
153
|
+
title="Click to scroll to element"
|
|
154
|
+
@click=${(e) => this._handleBadgeClick(item, e)}
|
|
155
|
+
class="se-shrink-0 se-w-2 se-h-2 se-rounded-full se-border-none se-cursor-pointer"
|
|
156
|
+
style="background:#22c55e"
|
|
157
|
+
></button>`;
|
|
158
|
+
}
|
|
159
|
+
return html `<button type="button"
|
|
160
|
+
title="Click to navigate to page"
|
|
161
|
+
@click=${(e) => this._handleBadgeClick(item, e)}
|
|
162
|
+
class="se-shrink-0 se-w-2 se-h-2 se-rounded-full se-border-none se-cursor-pointer"
|
|
163
|
+
style="background:#ef4444"
|
|
164
|
+
></button>`;
|
|
165
|
+
};
|
|
166
|
+
this._renderEditMode = (item) => {
|
|
167
|
+
const tip = item.tip;
|
|
168
|
+
return html `
|
|
169
|
+
<div class="se-py-1">
|
|
170
|
+
<div class="se-flex se-items-center se-gap-2 se-mb-3 se-text-[13px] se-font-semibold se-text-text-primary">
|
|
171
|
+
<span>🧭</span>
|
|
172
|
+
<span>${item.summary}</span>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<div class="se-mb-3">
|
|
176
|
+
<label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Title</label>
|
|
177
|
+
<input type="text" .value=${tip.config.title}
|
|
178
|
+
@input=${(e) => this._handleFieldChange(item.index, 'title', e.target.value)}
|
|
179
|
+
class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div class="se-mb-3">
|
|
183
|
+
<label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Description</label>
|
|
184
|
+
<input type="text" .value=${tip.config.description}
|
|
185
|
+
@input=${(e) => this._handleFieldChange(item.index, 'description', e.target.value)}
|
|
186
|
+
class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
<div class="se-mb-3">
|
|
190
|
+
<label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Link URL</label>
|
|
191
|
+
<input type="text" .value=${tip.config.href || ''} placeholder="Optional"
|
|
192
|
+
@input=${(e) => this._handleFieldChange(item.index, 'href', e.target.value)}
|
|
193
|
+
class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<div class="se-mb-3">
|
|
197
|
+
<label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Icon</label>
|
|
198
|
+
<input type="text" .value=${tip.config.icon || ''} placeholder="e.g., 🧭"
|
|
199
|
+
@input=${(e) => this._handleFieldChange(item.index, 'icon', e.target.value)}
|
|
200
|
+
class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<div class="se-mb-3">
|
|
204
|
+
<label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Category</label>
|
|
205
|
+
<input type="text" .value=${tip.config.category || ''} placeholder="Optional"
|
|
206
|
+
@input=${(e) => this._handleFieldChange(item.index, 'category', e.target.value)}
|
|
207
|
+
class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
${tip.rationale
|
|
211
|
+
? html `
|
|
212
|
+
<div>
|
|
213
|
+
<span class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">AI Rationale</span>
|
|
214
|
+
<div class="se-p-2 se-rounded se-border se-border-dashed se-border-border-primary se-bg-card-bg se-text-text-secondary se-text-xs se-mb-2">
|
|
215
|
+
${tip.rationale.why}
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
`
|
|
219
|
+
: nothing}
|
|
220
|
+
</div>
|
|
221
|
+
`;
|
|
222
|
+
};
|
|
223
|
+
this._renderListMode = (items) => {
|
|
224
|
+
if (items.length === 0) {
|
|
225
|
+
return html `<div class="se-text-center se-py-8 se-px-4 se-text-text-secondary se-text-sm">
|
|
226
|
+
No tips configured.
|
|
227
|
+
</div>`;
|
|
228
|
+
}
|
|
229
|
+
return html `
|
|
230
|
+
<div class="se-text-[11px] se-font-semibold se-uppercase se-tracking-wider se-text-text-secondary se-mb-2 se-px-1">
|
|
231
|
+
TIPS <span class="se-text-text-tertiary se-font-normal">${items.length}</span>
|
|
232
|
+
</div>
|
|
233
|
+
${items.map((item) => html `
|
|
234
|
+
<div
|
|
235
|
+
data-item-key=${item.key}
|
|
236
|
+
@click=${() => this._handleItemClick(item.key)}
|
|
237
|
+
class="se-p-3 se-rounded-lg se-border se-border-border-primary se-bg-card-bg se-cursor-pointer se-mb-2 se-transition-all hover:se-border-pink-4/40 hover:se-bg-pink-4/5"
|
|
238
|
+
>
|
|
239
|
+
<div class="se-flex se-items-center se-gap-2">
|
|
240
|
+
${this._renderDetectionBadge(item)}
|
|
241
|
+
<span class="se-flex-1 se-overflow-hidden se-text-ellipsis se-whitespace-nowrap se-text-sm se-text-text-primary">
|
|
242
|
+
${item.summary}
|
|
243
|
+
</span>
|
|
244
|
+
</div>
|
|
245
|
+
${item.trigger !== 'All pages'
|
|
246
|
+
? html `
|
|
247
|
+
<div class="se-text-[10px] se-text-text-tertiary se-mt-1">📍 ${item.trigger}</div>
|
|
248
|
+
`
|
|
249
|
+
: nothing}
|
|
250
|
+
${item.rationale
|
|
251
|
+
? html `
|
|
252
|
+
<div class="se-text-[10px] se-text-text-tertiary se-mt-1">WHY: ${item.rationale}</div>
|
|
253
|
+
`
|
|
254
|
+
: nothing}
|
|
255
|
+
</div>
|
|
256
|
+
`)}
|
|
257
|
+
`;
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
createRenderRoot() {
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
263
|
+
connectedCallback() {
|
|
264
|
+
super.connectedCallback();
|
|
265
|
+
window.addEventListener('popstate', this._onPopstate);
|
|
266
|
+
// Run detection on an interval (matches React's 2s interval)
|
|
267
|
+
this._detectionInterval = setInterval(() => this._runDetection(), 2000);
|
|
268
|
+
}
|
|
269
|
+
disconnectedCallback() {
|
|
270
|
+
window.removeEventListener('popstate', this._onPopstate);
|
|
271
|
+
if (this._detectionInterval) {
|
|
272
|
+
clearInterval(this._detectionInterval);
|
|
273
|
+
this._detectionInterval = null;
|
|
274
|
+
}
|
|
275
|
+
super.disconnectedCallback();
|
|
276
|
+
}
|
|
277
|
+
firstUpdated() {
|
|
278
|
+
this._runDetection();
|
|
279
|
+
// No auto-dirty on load — only dirty when user makes changes (matching React behavior).
|
|
280
|
+
}
|
|
281
|
+
render() {
|
|
282
|
+
if (!this.config) {
|
|
283
|
+
return html `<div class="se-p-8 se-text-center se-text-text-secondary se-text-sm">Loading...</div>`;
|
|
284
|
+
}
|
|
285
|
+
const items = flattenItems(this.config);
|
|
286
|
+
const editItem = this._editingKey !== null ? items.find((it) => it.key === this._editingKey) : null;
|
|
287
|
+
return html `
|
|
288
|
+
<div class="se-flex se-flex-col se-h-full">
|
|
289
|
+
<!-- Header (no Back button — panel provides that) -->
|
|
290
|
+
<div class="se-px-4 se-pt-3 se-pb-1">
|
|
291
|
+
<h2 class="se-m-0 se-text-base se-font-semibold se-text-text-primary">Navigation Tips</h2>
|
|
292
|
+
<p class="se-m-0 se-mt-0.5 se-text-xs se-text-text-secondary">
|
|
293
|
+
${items.length} tip${items.length !== 1 ? 's' : ''}
|
|
294
|
+
</p>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<div class="se-flex-1 se-overflow-auto se-p-4">
|
|
298
|
+
${editItem
|
|
299
|
+
? html `
|
|
300
|
+
<button type="button" @click=${() => {
|
|
301
|
+
this._editingKey = null;
|
|
302
|
+
}}
|
|
303
|
+
class="se-mb-3 se-py-1 se-px-2 se-rounded se-border-none se-bg-card-bg se-text-text-secondary se-text-xs se-cursor-pointer"
|
|
304
|
+
>← Back to list</button>
|
|
305
|
+
${this._renderEditMode(editItem)}
|
|
306
|
+
`
|
|
307
|
+
: this._renderListMode(items)}
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
`;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
NavEditorLit.properties = {
|
|
314
|
+
config: { attribute: false },
|
|
315
|
+
onChange: { attribute: false },
|
|
316
|
+
_editingKey: { state: true },
|
|
317
|
+
_detectionMap: { state: true },
|
|
318
|
+
};
|
|
319
|
+
customElements.define('se-nav-editor', NavEditorLit);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Nav - Runtime Module (Lit)
|
|
3
|
+
*
|
|
4
|
+
* Runtime manifest for the navigation tips accordion adaptive.
|
|
5
|
+
* Uses the Lit web component mountable instead of the React one.
|
|
6
|
+
* Includes widget-based nav tips and navigation action executors
|
|
7
|
+
* (scrollTo, navigate) previously in adaptive-navigation.
|
|
8
|
+
*/
|
|
9
|
+
import type { ActionExecutor, NavConfig, NavigateAction, NavWidgetRuntime, ScrollToAction } from './types';
|
|
10
|
+
/**
|
|
11
|
+
* Execute a scrollTo action
|
|
12
|
+
*/
|
|
13
|
+
export declare const executeScrollTo: ActionExecutor<ScrollToAction>;
|
|
14
|
+
/**
|
|
15
|
+
* Try to navigate using the host framework's native router.
|
|
16
|
+
* Returns true if a framework router handled the navigation,
|
|
17
|
+
* false if no framework was detected (caller should use pushState or location.href).
|
|
18
|
+
*
|
|
19
|
+
* Using the native router preserves SPA behavior (no full reload),
|
|
20
|
+
* layout state, scroll position, and framework-specific features
|
|
21
|
+
* (RSC streaming, view transitions, etc.).
|
|
22
|
+
*/
|
|
23
|
+
export declare function navigateWithFrameworkRouter(url: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Execute a navigate action
|
|
26
|
+
*/
|
|
27
|
+
export declare const executeNavigate: ActionExecutor<NavigateAction>;
|
|
28
|
+
/**
|
|
29
|
+
* NavWidgetLitMountable — Mounts the `<syntro-nav-tips>` Lit web component.
|
|
30
|
+
*
|
|
31
|
+
* Drop-in companion to NavMountableWidget that avoids React/ReactDOM entirely.
|
|
32
|
+
* Self-registers the custom element on first use.
|
|
33
|
+
*/
|
|
34
|
+
export declare const NavWidgetLitMountable: {
|
|
35
|
+
mount(container: HTMLElement, config?: NavConfig & {
|
|
36
|
+
runtime?: NavWidgetRuntime;
|
|
37
|
+
instanceId?: string;
|
|
38
|
+
}): () => void;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* All executors provided by this app.
|
|
42
|
+
* These are registered with the runtime's ExecutorRegistry.
|
|
43
|
+
*/
|
|
44
|
+
export declare const executors: readonly [{
|
|
45
|
+
readonly kind: "navigation:scrollTo";
|
|
46
|
+
readonly executor: ActionExecutor<ScrollToAction>;
|
|
47
|
+
}, {
|
|
48
|
+
readonly kind: "navigation:navigate";
|
|
49
|
+
readonly executor: ActionExecutor<NavigateAction>;
|
|
50
|
+
}];
|
|
51
|
+
/**
|
|
52
|
+
* Runtime manifest for adaptive-nav (Lit variant).
|
|
53
|
+
*
|
|
54
|
+
* Provides:
|
|
55
|
+
* - Navigation action executors (scrollTo, navigate)
|
|
56
|
+
* - Widget-based nav tips accordion using the Lit web component
|
|
57
|
+
*/
|
|
58
|
+
export declare const runtime: {
|
|
59
|
+
id: string;
|
|
60
|
+
version: string;
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
/**
|
|
64
|
+
* Navigation action executors (scrollTo, navigate).
|
|
65
|
+
*/
|
|
66
|
+
executors: readonly [{
|
|
67
|
+
readonly kind: "navigation:scrollTo";
|
|
68
|
+
readonly executor: ActionExecutor<ScrollToAction>;
|
|
69
|
+
}, {
|
|
70
|
+
readonly kind: "navigation:navigate";
|
|
71
|
+
readonly executor: ActionExecutor<NavigateAction>;
|
|
72
|
+
}];
|
|
73
|
+
/**
|
|
74
|
+
* Widget definitions for the runtime's WidgetRegistry.
|
|
75
|
+
*/
|
|
76
|
+
widgets: {
|
|
77
|
+
id: string;
|
|
78
|
+
component: {
|
|
79
|
+
mount(container: HTMLElement, config?: NavConfig & {
|
|
80
|
+
runtime?: NavWidgetRuntime;
|
|
81
|
+
instanceId?: string;
|
|
82
|
+
}): () => void;
|
|
83
|
+
};
|
|
84
|
+
metadata: {
|
|
85
|
+
name: string;
|
|
86
|
+
description: string;
|
|
87
|
+
icon: string;
|
|
88
|
+
};
|
|
89
|
+
}[];
|
|
90
|
+
/**
|
|
91
|
+
* Extract notify watcher entries from tile config props.
|
|
92
|
+
* The runtime evaluates these continuously (even with drawer closed)
|
|
93
|
+
* and publishes nav:tip_revealed when triggerWhen transitions false → true.
|
|
94
|
+
*/
|
|
95
|
+
notifyWatchers(props: Record<string, unknown>): {
|
|
96
|
+
id: string;
|
|
97
|
+
strategy: import("./types").DecisionStrategy<boolean>;
|
|
98
|
+
eventName: string;
|
|
99
|
+
eventProps: {
|
|
100
|
+
tipId: string;
|
|
101
|
+
title: string | undefined;
|
|
102
|
+
body: string | undefined;
|
|
103
|
+
icon: string | undefined;
|
|
104
|
+
};
|
|
105
|
+
}[];
|
|
106
|
+
};
|
|
107
|
+
export default runtime;
|
|
108
|
+
//# sourceMappingURL=runtime-lit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-lit.d.ts","sourceRoot":"","sources":["../src/runtime-lit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,EACT,cAAc,EAEd,gBAAgB,EAChB,cAAc,EACf,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,cAAc,CA+B1D,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAgDhE;AAgBD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,cAAc,CAuC1D,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;qBAEnB,WAAW,WACb,SAAS,GAAG;QAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CA2B3E,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;EAGZ,CAAC;AAMX;;;;;;GAMG;AACH,eAAO,MAAM,OAAO;;;;;IAMlB;;OAEG;;;;;;;;IAGH;;OAEG;;;;6BAnEU,WAAW,WACb,SAAS,GAAG;gBAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC;gBAAC,UAAU,CAAC,EAAE,MAAM,CAAA;aAAE;;;;;;;;IA+E1E;;;;OAIG;0BACmB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;CAgB9C,CAAC;AAEF,eAAe,OAAO,CAAC"}
|