@syntrologie/adapt-nav 0.0.0-semantically-released

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.
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Adaptive Nav - NavWidget Component
3
+ *
4
+ * React component that renders a navigation link list with per-item
5
+ * conditional visibility based on showWhen decision strategies.
6
+ *
7
+ * Demonstrates the compositional action pattern where child actions
8
+ * (nav:link) serve as configuration data for the parent widget.
9
+ */
10
+ import type { NavWidgetProps, NavConfig, NavWidgetRuntime } from './types';
11
+ /**
12
+ * NavWidget - Renders a navigation link list with per-item activation.
13
+ *
14
+ * This component demonstrates the compositional action pattern:
15
+ * - Parent (NavWidget) receives `config.actions` array
16
+ * - Each action has optional `showWhen` for per-item visibility
17
+ * - Parent evaluates showWhen and filters visible links
18
+ * - Parent manages re-rendering on context changes
19
+ */
20
+ export declare function NavWidget({ config, runtime, instanceId }: NavWidgetProps): import("react/jsx-runtime").JSX.Element | null;
21
+ /**
22
+ * Mountable widget interface for the runtime's WidgetRegistry.
23
+ */
24
+ export declare const NavMountableWidget: {
25
+ mount(container: HTMLElement, config?: NavConfig & {
26
+ runtime?: NavWidgetRuntime;
27
+ instanceId?: string;
28
+ }): () => void;
29
+ };
30
+ export default NavWidget;
31
+ //# sourceMappingURL=NavWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavWidget.d.ts","sourceRoot":"","sources":["../src/NavWidget.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAiB,SAAS,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA8G1F;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,cAAc,kDAgFxE;AAMD;;GAEG;AACH,eAAO,MAAM,kBAAkB;qBAEhB,WAAW,WACb,SAAS,GAAG;QAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAsC3E,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,193 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Adaptive Nav - NavWidget Component
4
+ *
5
+ * React component that renders a navigation link list with per-item
6
+ * conditional visibility based on showWhen decision strategies.
7
+ *
8
+ * Demonstrates the compositional action pattern where child actions
9
+ * (nav:link) serve as configuration data for the parent widget.
10
+ */
11
+ import React, { useEffect, useReducer, useMemo, useCallback } from 'react';
12
+ // ============================================================================
13
+ // Styles
14
+ // ============================================================================
15
+ const baseStyles = {
16
+ nav: {
17
+ display: 'flex',
18
+ gap: '4px',
19
+ padding: '8px',
20
+ fontFamily: 'system-ui, -apple-system, sans-serif',
21
+ },
22
+ link: {
23
+ display: 'flex',
24
+ alignItems: 'center',
25
+ gap: '6px',
26
+ padding: '8px 12px',
27
+ borderRadius: '6px',
28
+ textDecoration: 'none',
29
+ fontSize: '14px',
30
+ fontWeight: 500,
31
+ transition: 'background-color 0.15s ease, color 0.15s ease',
32
+ cursor: 'pointer',
33
+ border: 'none',
34
+ background: 'transparent',
35
+ },
36
+ icon: {
37
+ fontSize: '16px',
38
+ },
39
+ externalIcon: {
40
+ fontSize: '12px',
41
+ opacity: 0.6,
42
+ },
43
+ };
44
+ const themeStyles = {
45
+ light: {
46
+ nav: {
47
+ backgroundColor: '#ffffff',
48
+ },
49
+ link: {
50
+ color: '#374151',
51
+ },
52
+ linkHover: {
53
+ backgroundColor: '#f3f4f6',
54
+ color: '#111827',
55
+ },
56
+ },
57
+ dark: {
58
+ nav: {
59
+ backgroundColor: '#1f2937',
60
+ },
61
+ link: {
62
+ color: '#d1d5db',
63
+ },
64
+ linkHover: {
65
+ backgroundColor: '#374151',
66
+ color: '#f9fafb',
67
+ },
68
+ },
69
+ };
70
+ function NavLinkComponent({ link, theme, onNavigate }) {
71
+ const [isHovered, setIsHovered] = React.useState(false);
72
+ const { label, href, icon, external } = link.config;
73
+ const colors = themeStyles[theme];
74
+ const style = {
75
+ ...baseStyles.link,
76
+ ...colors.link,
77
+ ...(isHovered ? colors.linkHover : {}),
78
+ };
79
+ const handleClick = (e) => {
80
+ e.preventDefault();
81
+ onNavigate(href, external ?? false);
82
+ };
83
+ return (_jsxs("a", { href: href, onClick: handleClick, style: style, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), target: external ? '_blank' : undefined, rel: external ? 'noopener noreferrer' : undefined, children: [icon && _jsx("span", { style: baseStyles.icon, children: icon }), _jsx("span", { children: label }), external && _jsx("span", { style: baseStyles.externalIcon, children: "\u2197" })] }));
84
+ }
85
+ // ============================================================================
86
+ // NavWidget Component
87
+ // ============================================================================
88
+ /**
89
+ * NavWidget - Renders a navigation link list with per-item activation.
90
+ *
91
+ * This component demonstrates the compositional action pattern:
92
+ * - Parent (NavWidget) receives `config.actions` array
93
+ * - Each action has optional `showWhen` for per-item visibility
94
+ * - Parent evaluates showWhen and filters visible links
95
+ * - Parent manages re-rendering on context changes
96
+ */
97
+ export function NavWidget({ config, runtime, instanceId }) {
98
+ // Force re-render when context changes
99
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
100
+ // Subscribe to context changes for reactive updates
101
+ useEffect(() => {
102
+ const unsubscribe = runtime.context.subscribe(() => {
103
+ forceUpdate();
104
+ });
105
+ return unsubscribe;
106
+ }, [runtime.context]);
107
+ // Filter visible links based on per-item showWhen
108
+ const visibleLinks = useMemo(() => {
109
+ return config.actions.filter((link) => {
110
+ // No showWhen = always visible
111
+ if (!link.showWhen)
112
+ return true;
113
+ // Evaluate the decision strategy
114
+ const result = runtime.evaluateSync(link.showWhen);
115
+ return result.value;
116
+ });
117
+ }, [config.actions, runtime]);
118
+ // Resolve theme (auto → detect system preference)
119
+ const resolvedTheme = useMemo(() => {
120
+ if (config.theme !== 'auto')
121
+ return config.theme;
122
+ // Check system preference (SSR-safe)
123
+ if (typeof window !== 'undefined') {
124
+ return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
125
+ }
126
+ return 'light';
127
+ }, [config.theme]);
128
+ // Handle navigation with event publishing
129
+ const handleNavigate = useCallback((href, external) => {
130
+ // Publish navigation event for analytics
131
+ runtime.events.publish('nav:click', {
132
+ instanceId,
133
+ href,
134
+ external,
135
+ timestamp: Date.now(),
136
+ });
137
+ // Perform navigation
138
+ if (external) {
139
+ window.open(href, '_blank', 'noopener,noreferrer');
140
+ }
141
+ else {
142
+ window.location.href = href;
143
+ }
144
+ }, [runtime.events, instanceId]);
145
+ // Compute nav styles
146
+ const navStyle = {
147
+ ...baseStyles.nav,
148
+ ...themeStyles[resolvedTheme].nav,
149
+ flexDirection: config.layout === 'vertical' ? 'column' : 'row',
150
+ };
151
+ // Empty state
152
+ if (visibleLinks.length === 0) {
153
+ return null;
154
+ }
155
+ return (_jsx("nav", { style: navStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: visibleLinks.map((link, index) => (_jsx(NavLinkComponent, { link: link, theme: resolvedTheme, onNavigate: handleNavigate }, link.config.href + index))) }));
156
+ }
157
+ // ============================================================================
158
+ // Mountable Widget Interface
159
+ // ============================================================================
160
+ /**
161
+ * Mountable widget interface for the runtime's WidgetRegistry.
162
+ */
163
+ export const NavMountableWidget = {
164
+ mount(container, config) {
165
+ // This is a simplified mount for non-React environments
166
+ // In practice, the runtime handles React rendering
167
+ const { runtime, instanceId: _instanceId = 'nav-widget', ...navConfig } = config || {
168
+ layout: 'horizontal',
169
+ theme: 'auto',
170
+ actions: [],
171
+ };
172
+ // Create simple HTML fallback if no runtime
173
+ if (!runtime) {
174
+ const links = navConfig.actions || [];
175
+ container.innerHTML = `
176
+ <nav style="display: flex; gap: 8px; padding: 8px; font-family: system-ui;">
177
+ ${links
178
+ .map((link) => `
179
+ <a href="${link.config.href}" style="padding: 8px 12px; text-decoration: none; color: #374151;">
180
+ ${link.config.icon ? `<span>${link.config.icon}</span>` : ''}
181
+ ${link.config.label}
182
+ </a>
183
+ `)
184
+ .join('')}
185
+ </nav>
186
+ `;
187
+ }
188
+ return () => {
189
+ container.innerHTML = '';
190
+ };
191
+ },
192
+ };
193
+ export default NavWidget;
package/dist/cdn.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * CDN Entry Point for Adaptive Nav
3
+ *
4
+ * This module is bundled for CDN delivery and self-registers with the global
5
+ * SynOS app registry when loaded dynamically via the AppLoader.
6
+ */
7
+ /**
8
+ * App manifest for registry registration.
9
+ * Follows the AppManifest interface expected by AppLoader/AppRegistry.
10
+ */
11
+ export declare const manifest: {
12
+ id: string;
13
+ version: string;
14
+ name: string;
15
+ description: string;
16
+ runtime: {
17
+ actions: never[];
18
+ widgets: {
19
+ id: string;
20
+ component: {
21
+ mount(container: HTMLElement, config?: import("./types").NavConfig & {
22
+ runtime?: import("./types").NavWidgetRuntime;
23
+ instanceId?: string;
24
+ }): () => void;
25
+ };
26
+ metadata: {
27
+ name: string;
28
+ description: string;
29
+ icon: string;
30
+ };
31
+ }[];
32
+ };
33
+ metadata: {
34
+ isBuiltIn: boolean;
35
+ };
36
+ };
37
+ export default manifest;
38
+ //# sourceMappingURL=cdn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;2BA2B+iK,CAAC;8BAA8B,CAAC;;;;;;;;;;;;;CAdnmK,CAAC;AAaF,eAAe,QAAQ,CAAC"}
package/dist/cdn.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * CDN Entry Point for Adaptive Nav
3
+ *
4
+ * This module is bundled for CDN delivery and self-registers with the global
5
+ * SynOS app registry when loaded dynamically via the AppLoader.
6
+ */
7
+ import { runtime } from './runtime';
8
+ /**
9
+ * App manifest for registry registration.
10
+ * Follows the AppManifest interface expected by AppLoader/AppRegistry.
11
+ */
12
+ export const manifest = {
13
+ id: 'nav',
14
+ version: runtime.version,
15
+ name: runtime.name,
16
+ description: runtime.description,
17
+ runtime: {
18
+ // Nav is widget-based, no action executors
19
+ actions: [],
20
+ widgets: runtime.widgets,
21
+ },
22
+ metadata: {
23
+ isBuiltIn: false,
24
+ },
25
+ };
26
+ /**
27
+ * Self-register with global registry if available.
28
+ * This happens when loaded via script tag (UMD).
29
+ */
30
+ if (typeof window !== 'undefined') {
31
+ const globalRegistry = window.__SYNOS_APP_REGISTRY__;
32
+ if (globalRegistry && typeof globalRegistry.register === 'function') {
33
+ globalRegistry.register(manifest);
34
+ }
35
+ }
36
+ export default manifest;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Adaptive Nav - Editor Component
3
+ *
4
+ * Visual editor panel for configuring navigation links.
5
+ */
6
+ import type { EditorPanelProps } from './types';
7
+ export declare function NavEditor({ config, onChange, editor }: EditorPanelProps): import("react/jsx-runtime").JSX.Element;
8
+ /**
9
+ * Editor panel configuration for the app registry.
10
+ */
11
+ export declare const editorPanel: {
12
+ title: string;
13
+ icon: string;
14
+ description: string;
15
+ };
16
+ export default NavEditor;
17
+ //# sourceMappingURL=editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqLhD,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAkMvE;AAED;;GAEG;AACH,eAAO,MAAM,WAAW;;;;CAIvB,CAAC;AAEF,eAAe,SAAS,CAAC"}
package/dist/editor.js ADDED
@@ -0,0 +1,252 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // Editor Styles
4
+ // ============================================================================
5
+ const styles = {
6
+ container: {
7
+ display: 'flex',
8
+ flexDirection: 'column',
9
+ height: '100%',
10
+ fontFamily: 'system-ui, -apple-system, sans-serif',
11
+ },
12
+ header: {
13
+ padding: '16px',
14
+ borderBottom: '1px solid #334155',
15
+ display: 'flex',
16
+ alignItems: 'center',
17
+ gap: '12px',
18
+ },
19
+ backButton: {
20
+ padding: '6px 12px',
21
+ borderRadius: '6px',
22
+ border: 'none',
23
+ backgroundColor: 'rgba(255,255,255,0.05)',
24
+ color: '#94a3b8',
25
+ fontSize: '13px',
26
+ cursor: 'pointer',
27
+ },
28
+ title: {
29
+ margin: 0,
30
+ fontSize: '15px',
31
+ fontWeight: 600,
32
+ color: '#f8fafc',
33
+ },
34
+ subtitle: {
35
+ margin: '2px 0 0 0',
36
+ fontSize: '11px',
37
+ color: '#64748b',
38
+ },
39
+ content: {
40
+ flex: 1,
41
+ overflow: 'auto',
42
+ padding: '16px',
43
+ },
44
+ section: {
45
+ marginBottom: '24px',
46
+ },
47
+ sectionTitle: {
48
+ fontSize: '12px',
49
+ fontWeight: 600,
50
+ color: '#94a3b8',
51
+ textTransform: 'uppercase',
52
+ letterSpacing: '0.05em',
53
+ marginBottom: '12px',
54
+ },
55
+ select: {
56
+ width: '100%',
57
+ padding: '10px 12px',
58
+ borderRadius: '6px',
59
+ border: '1px solid rgba(255,255,255,0.1)',
60
+ backgroundColor: 'rgba(255,255,255,0.05)',
61
+ color: '#f8fafc',
62
+ fontSize: '13px',
63
+ cursor: 'pointer',
64
+ },
65
+ addButton: {
66
+ width: '100%',
67
+ padding: '12px',
68
+ borderRadius: '8px',
69
+ border: '1px dashed rgba(59, 130, 246, 0.3)',
70
+ background: 'rgba(59, 130, 246, 0.05)',
71
+ color: '#3b82f6',
72
+ fontSize: '13px',
73
+ fontWeight: 600,
74
+ cursor: 'pointer',
75
+ marginBottom: '16px',
76
+ },
77
+ linkCard: {
78
+ padding: '12px',
79
+ borderRadius: '8px',
80
+ border: '1px solid rgba(255,255,255,0.08)',
81
+ background: 'rgba(255,255,255,0.02)',
82
+ marginBottom: '8px',
83
+ },
84
+ linkHeader: {
85
+ display: 'flex',
86
+ alignItems: 'center',
87
+ gap: '12px',
88
+ marginBottom: '12px',
89
+ },
90
+ linkIcon: {
91
+ fontSize: '20px',
92
+ },
93
+ linkInfo: {
94
+ flex: 1,
95
+ },
96
+ linkLabel: {
97
+ fontSize: '14px',
98
+ fontWeight: 500,
99
+ color: '#f8fafc',
100
+ },
101
+ linkHref: {
102
+ fontSize: '12px',
103
+ color: '#64748b',
104
+ },
105
+ removeButton: {
106
+ padding: '4px 8px',
107
+ borderRadius: '4px',
108
+ border: 'none',
109
+ background: 'rgba(239, 68, 68, 0.1)',
110
+ color: '#ef4444',
111
+ fontSize: '12px',
112
+ cursor: 'pointer',
113
+ },
114
+ inputGroup: {
115
+ marginBottom: '8px',
116
+ },
117
+ inputLabel: {
118
+ display: 'block',
119
+ fontSize: '11px',
120
+ color: '#94a3b8',
121
+ marginBottom: '4px',
122
+ },
123
+ input: {
124
+ width: '100%',
125
+ padding: '8px 10px',
126
+ borderRadius: '4px',
127
+ border: '1px solid rgba(255,255,255,0.1)',
128
+ backgroundColor: 'rgba(255,255,255,0.05)',
129
+ color: '#f8fafc',
130
+ fontSize: '13px',
131
+ },
132
+ checkbox: {
133
+ display: 'flex',
134
+ alignItems: 'center',
135
+ gap: '8px',
136
+ fontSize: '13px',
137
+ color: '#d1d5db',
138
+ },
139
+ emptyState: {
140
+ textAlign: 'center',
141
+ padding: '32px 16px',
142
+ color: '#64748b',
143
+ fontSize: '13px',
144
+ },
145
+ footer: {
146
+ padding: '12px 16px',
147
+ borderTop: '1px solid #334155',
148
+ display: 'flex',
149
+ gap: '8px',
150
+ },
151
+ saveButton: {
152
+ flex: 1,
153
+ padding: '10px',
154
+ borderRadius: '8px',
155
+ border: 'none',
156
+ background: 'rgba(59, 130, 246, 0.15)',
157
+ color: '#3b82f6',
158
+ fontSize: '13px',
159
+ fontWeight: 600,
160
+ cursor: 'pointer',
161
+ },
162
+ publishButton: {
163
+ flex: 1,
164
+ padding: '10px',
165
+ borderRadius: '8px',
166
+ border: 'none',
167
+ background: '#22c55e',
168
+ color: 'white',
169
+ fontSize: '13px',
170
+ fontWeight: 600,
171
+ cursor: 'pointer',
172
+ },
173
+ };
174
+ // ============================================================================
175
+ // NavEditor Component
176
+ // ============================================================================
177
+ export function NavEditor({ config, onChange, editor }) {
178
+ const typedConfig = config;
179
+ const links = typedConfig.actions || [];
180
+ // Add a new link
181
+ const handleAddLink = () => {
182
+ const newLink = {
183
+ kind: 'nav:link',
184
+ config: {
185
+ label: 'New Link',
186
+ href: '/',
187
+ icon: '🔗',
188
+ external: false,
189
+ },
190
+ showWhen: null,
191
+ };
192
+ onChange({
193
+ ...config,
194
+ actions: [...links, newLink],
195
+ });
196
+ editor.setDirty(true);
197
+ };
198
+ // Remove a link
199
+ const handleRemoveLink = (index) => {
200
+ const newLinks = links.filter((_, i) => i !== index);
201
+ onChange({
202
+ ...config,
203
+ actions: newLinks,
204
+ });
205
+ editor.setDirty(true);
206
+ };
207
+ // Update a link
208
+ const handleUpdateLink = (index, updates) => {
209
+ const newLinks = links.map((link, i) => {
210
+ if (i !== index)
211
+ return link;
212
+ return {
213
+ ...link,
214
+ config: {
215
+ ...link.config,
216
+ ...updates,
217
+ },
218
+ };
219
+ });
220
+ onChange({
221
+ ...config,
222
+ actions: newLinks,
223
+ });
224
+ editor.setDirty(true);
225
+ };
226
+ // Update layout
227
+ const handleLayoutChange = (e) => {
228
+ onChange({
229
+ ...config,
230
+ layout: e.target.value,
231
+ });
232
+ editor.setDirty(true);
233
+ };
234
+ // Update theme
235
+ const handleThemeChange = (e) => {
236
+ onChange({
237
+ ...config,
238
+ theme: e.target.value,
239
+ });
240
+ editor.setDirty(true);
241
+ };
242
+ return (_jsxs("div", { style: styles.container, children: [_jsxs("div", { style: styles.header, children: [_jsx("button", { onClick: () => editor.navigateHome(), style: styles.backButton, children: "\u2190 Back" }), _jsxs("div", { children: [_jsx("h2", { style: styles.title, children: "Navigation Links" }), _jsx("p", { style: styles.subtitle, children: "Configure navigation with per-item visibility" })] })] }), _jsxs("div", { style: styles.content, children: [_jsxs("div", { style: styles.section, children: [_jsx("div", { style: styles.sectionTitle, children: "Layout" }), _jsxs("select", { value: typedConfig.layout || 'horizontal', onChange: handleLayoutChange, style: styles.select, children: [_jsx("option", { value: "horizontal", children: "Horizontal" }), _jsx("option", { value: "vertical", children: "Vertical" })] })] }), _jsxs("div", { style: styles.section, children: [_jsx("div", { style: styles.sectionTitle, children: "Theme" }), _jsxs("select", { value: typedConfig.theme || 'auto', onChange: handleThemeChange, style: styles.select, children: [_jsx("option", { value: "auto", children: "Auto (System)" }), _jsx("option", { value: "light", children: "Light" }), _jsx("option", { value: "dark", children: "Dark" })] })] }), _jsxs("div", { style: styles.section, children: [_jsx("div", { style: styles.sectionTitle, children: "Navigation Links" }), _jsx("button", { onClick: handleAddLink, style: styles.addButton, children: "+ Add Link" }), links.map((link, index) => (_jsxs("div", { style: styles.linkCard, children: [_jsxs("div", { style: styles.linkHeader, children: [_jsx("span", { style: styles.linkIcon, children: link.config.icon || '🔗' }), _jsxs("div", { style: styles.linkInfo, children: [_jsx("div", { style: styles.linkLabel, children: link.config.label }), _jsx("div", { style: styles.linkHref, children: link.config.href })] }), _jsx("button", { onClick: () => handleRemoveLink(index), style: styles.removeButton, children: "Remove" })] }), _jsxs("div", { style: styles.inputGroup, children: [_jsx("label", { style: styles.inputLabel, children: "Label" }), _jsx("input", { type: "text", value: link.config.label, onChange: (e) => handleUpdateLink(index, { label: e.target.value }), style: styles.input })] }), _jsxs("div", { style: styles.inputGroup, children: [_jsx("label", { style: styles.inputLabel, children: "URL" }), _jsx("input", { type: "text", value: link.config.href, onChange: (e) => handleUpdateLink(index, { href: e.target.value }), style: styles.input })] }), _jsxs("div", { style: styles.inputGroup, children: [_jsx("label", { style: styles.inputLabel, children: "Icon (emoji)" }), _jsx("input", { type: "text", value: link.config.icon || '', onChange: (e) => handleUpdateLink(index, { icon: e.target.value }), style: styles.input, placeholder: "e.g., \uD83C\uDFE0" })] }), _jsxs("label", { style: styles.checkbox, children: [_jsx("input", { type: "checkbox", checked: link.config.external || false, onChange: (e) => handleUpdateLink(index, { external: e.target.checked }) }), "Open in new tab"] })] }, index))), links.length === 0 && (_jsx("div", { style: styles.emptyState, children: "No links configured. Click the button above to add one." }))] })] }), _jsxs("div", { style: styles.footer, children: [_jsx("button", { onClick: () => editor.save(), style: styles.saveButton, children: "Save Draft" }), _jsx("button", { onClick: () => editor.publish(), style: styles.publishButton, children: "Publish" })] })] }));
243
+ }
244
+ /**
245
+ * Editor panel configuration for the app registry.
246
+ */
247
+ export const editorPanel = {
248
+ title: 'Navigation',
249
+ icon: '🔗',
250
+ description: 'Navigation link list with per-item visibility',
251
+ };
252
+ export default NavEditor;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Adaptive Nav - Runtime Module
3
+ *
4
+ * Runtime manifest for the navigation link list adaptive.
5
+ * This is a widget-based adaptive with no action executors.
6
+ */
7
+ /**
8
+ * Runtime manifest for adaptive-nav.
9
+ *
10
+ * Note: This adaptive is widget-based, not action-based.
11
+ * The `nav:link` actions are compositional - they're rendered by
12
+ * the widget, not executed by the runtime.
13
+ */
14
+ export declare const runtime: {
15
+ id: string;
16
+ version: string;
17
+ name: string;
18
+ description: string;
19
+ /**
20
+ * No action executors - nav:link actions are compositional,
21
+ * meaning they serve as configuration for the NavWidget.
22
+ */
23
+ executors: never[];
24
+ /**
25
+ * Widget definitions for the runtime's WidgetRegistry.
26
+ */
27
+ widgets: {
28
+ id: string;
29
+ component: {
30
+ mount(container: HTMLElement, config?: import("./types").NavConfig & {
31
+ runtime?: import("./types").NavWidgetRuntime;
32
+ instanceId?: string;
33
+ }): () => void;
34
+ };
35
+ metadata: {
36
+ name: string;
37
+ description: string;
38
+ icon: string;
39
+ };
40
+ }[];
41
+ };
42
+ export default runtime;
43
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;;;;;GAMG;AACH,eAAO,MAAM,OAAO;;;;;IAMlB;;;OAGG;;IAGH;;OAEG;;;;;uBAeuwJ,CAAC;0BAA8B,CAAC;;;;;;;;;CAH3yJ,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Adaptive Nav - Runtime Module
3
+ *
4
+ * Runtime manifest for the navigation link list adaptive.
5
+ * This is a widget-based adaptive with no action executors.
6
+ */
7
+ import { NavMountableWidget } from './NavWidget';
8
+ // ============================================================================
9
+ // App Runtime Manifest
10
+ // ============================================================================
11
+ /**
12
+ * Runtime manifest for adaptive-nav.
13
+ *
14
+ * Note: This adaptive is widget-based, not action-based.
15
+ * The `nav:link` actions are compositional - they're rendered by
16
+ * the widget, not executed by the runtime.
17
+ */
18
+ export const runtime = {
19
+ id: 'adaptive-nav',
20
+ version: '1.0.0',
21
+ name: 'Navigation Links',
22
+ description: 'Widget-based navigation link list with per-item conditional visibility',
23
+ /**
24
+ * No action executors - nav:link actions are compositional,
25
+ * meaning they serve as configuration for the NavWidget.
26
+ */
27
+ executors: [],
28
+ /**
29
+ * Widget definitions for the runtime's WidgetRegistry.
30
+ */
31
+ widgets: [
32
+ {
33
+ id: 'adaptive-nav:links',
34
+ component: NavMountableWidget,
35
+ metadata: {
36
+ name: 'Navigation Links',
37
+ description: 'Horizontal or vertical navigation link list',
38
+ icon: '🔗',
39
+ },
40
+ },
41
+ ],
42
+ };
43
+ export default runtime;