@syntrologie/adapt-nav 2.8.0-canary.31 → 2.8.0-canary.310

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.
Files changed (144) hide show
  1. package/dist/NavWidgetLit.d.ts +56 -0
  2. package/dist/NavWidgetLit.d.ts.map +1 -0
  3. package/dist/NavWidgetLit.editable.d.ts +151 -0
  4. package/dist/NavWidgetLit.editable.d.ts.map +1 -0
  5. package/dist/NavWidgetLit.test.d.ts +8 -0
  6. package/dist/NavWidgetLit.test.d.ts.map +1 -0
  7. package/dist/chunk-SX36IHRC.js +640 -0
  8. package/dist/chunk-SX36IHRC.js.map +7 -0
  9. package/dist/editor.d.ts +66 -21
  10. package/dist/editor.d.ts.map +1 -1
  11. package/dist/editor.js +5627 -307
  12. package/dist/editor.js.map +7 -0
  13. package/dist/nav-item-editor.d.ts +43 -0
  14. package/dist/nav-item-editor.d.ts.map +1 -0
  15. package/dist/resolveNavTarget.d.ts +61 -0
  16. package/dist/resolveNavTarget.d.ts.map +1 -0
  17. package/dist/resolveNavTarget.test.d.ts +2 -0
  18. package/dist/resolveNavTarget.test.d.ts.map +1 -0
  19. package/dist/runtime.d.ts +22 -6
  20. package/dist/runtime.d.ts.map +1 -1
  21. package/dist/runtime.js +643 -142
  22. package/dist/runtime.js.map +7 -0
  23. package/dist/schema.d.ts +316 -174
  24. package/dist/schema.d.ts.map +1 -1
  25. package/dist/schema.js +155 -125
  26. package/dist/schema.js.map +7 -0
  27. package/dist/types.d.ts +7 -0
  28. package/dist/types.d.ts.map +1 -1
  29. package/package.json +12 -16
  30. package/dist/NavWidget.d.ts +0 -31
  31. package/dist/NavWidget.d.ts.map +0 -1
  32. package/dist/NavWidget.js +0 -491
  33. package/dist/cdn.d.ts +0 -62
  34. package/dist/cdn.d.ts.map +0 -1
  35. package/dist/cdn.js +0 -48
  36. package/dist/summarize.js +0 -51
  37. package/dist/types.js +0 -18
  38. package/node_modules/@syntro/design-system/README.md +0 -335
  39. package/node_modules/@syntro/design-system/dist/assets/syntrologie-logo.svg +0 -21
  40. package/node_modules/@syntro/design-system/dist/assets/syntrologie-logomark.svg +0 -10
  41. package/node_modules/@syntro/design-system/dist/index.d.ts +0 -8
  42. package/node_modules/@syntro/design-system/dist/index.d.ts.map +0 -1
  43. package/node_modules/@syntro/design-system/dist/index.js +0 -7
  44. package/node_modules/@syntro/design-system/dist/tailwind-preset.d.ts +0 -19
  45. package/node_modules/@syntro/design-system/dist/tailwind-preset.d.ts.map +0 -1
  46. package/node_modules/@syntro/design-system/dist/tailwind-preset.js +0 -453
  47. package/node_modules/@syntro/design-system/dist/tokens/colors.css +0 -464
  48. package/node_modules/@syntro/design-system/dist/tokens/colors.d.ts +0 -874
  49. package/node_modules/@syntro/design-system/dist/tokens/colors.d.ts.map +0 -1
  50. package/node_modules/@syntro/design-system/dist/tokens/colors.js +0 -564
  51. package/node_modules/@syntro/design-system/dist/tokens/effects.css +0 -43
  52. package/node_modules/@syntro/design-system/dist/tokens/effects.d.ts +0 -85
  53. package/node_modules/@syntro/design-system/dist/tokens/effects.d.ts.map +0 -1
  54. package/node_modules/@syntro/design-system/dist/tokens/effects.js +0 -77
  55. package/node_modules/@syntro/design-system/dist/tokens/index.d.ts +0 -10
  56. package/node_modules/@syntro/design-system/dist/tokens/index.d.ts.map +0 -1
  57. package/node_modules/@syntro/design-system/dist/tokens/index.js +0 -9
  58. package/node_modules/@syntro/design-system/package.json +0 -55
  59. package/node_modules/@syntro/design-system/src/assets/syntrologie-logo.svg +0 -21
  60. package/node_modules/@syntro/design-system/src/assets/syntrologie-logomark.svg +0 -10
  61. package/node_modules/@syntrologie/sdk-contracts/dist/index.d.ts +0 -129
  62. package/node_modules/@syntrologie/sdk-contracts/dist/index.js +0 -15
  63. package/node_modules/@syntrologie/sdk-contracts/dist/schemas.d.ts +0 -2225
  64. package/node_modules/@syntrologie/sdk-contracts/dist/schemas.js +0 -162
  65. package/node_modules/@syntrologie/sdk-contracts/package.json +0 -33
  66. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts +0 -2
  67. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts.map +0 -1
  68. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.js +0 -3
  69. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts +0 -34
  70. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts.map +0 -1
  71. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.js +0 -158
  72. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts +0 -7
  73. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts.map +0 -1
  74. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.js +0 -9
  75. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts +0 -23
  76. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts.map +0 -1
  77. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.js +0 -40
  78. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts +0 -7
  79. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts.map +0 -1
  80. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.js +0 -22
  81. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts +0 -8
  82. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts.map +0 -1
  83. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.js +0 -9
  84. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts +0 -7
  85. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts.map +0 -1
  86. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.js +0 -4
  87. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts +0 -7
  88. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts.map +0 -1
  89. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.js +0 -4
  90. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts +0 -13
  91. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts.map +0 -1
  92. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.js +0 -15
  93. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts +0 -7
  94. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts.map +0 -1
  95. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.js +0 -4
  96. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts +0 -9
  97. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts.map +0 -1
  98. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.js +0 -4
  99. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts +0 -8
  100. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts.map +0 -1
  101. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.js +0 -8
  102. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts +0 -7
  103. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts.map +0 -1
  104. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.js +0 -4
  105. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts +0 -25
  106. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts.map +0 -1
  107. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.js +0 -379
  108. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts +0 -8
  109. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts.map +0 -1
  110. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.js +0 -8
  111. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts +0 -8
  112. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts.map +0 -1
  113. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.js +0 -17
  114. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts +0 -32
  115. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts.map +0 -1
  116. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.js +0 -85
  117. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts +0 -6
  118. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts.map +0 -1
  119. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.js +0 -4
  120. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts +0 -8
  121. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts.map +0 -1
  122. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.js +0 -5
  123. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts +0 -12
  124. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts.map +0 -1
  125. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.js +0 -40
  126. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts +0 -26
  127. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts.map +0 -1
  128. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.js +0 -202
  129. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts +0 -8
  130. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts.map +0 -1
  131. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.js +0 -46
  132. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts +0 -24
  133. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts.map +0 -1
  134. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.js +0 -86
  135. package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts +0 -34
  136. package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts.map +0 -1
  137. package/node_modules/@syntrologie/shared-editor-ui/dist/index.js +0 -25
  138. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts +0 -37
  139. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts.map +0 -1
  140. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.js +0 -52
  141. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts +0 -22
  142. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts.map +0 -1
  143. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.js +0 -143
  144. package/node_modules/@syntrologie/shared-editor-ui/package.json +0 -45
package/dist/NavWidget.js DELETED
@@ -1,491 +0,0 @@
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 collapsible navigation tips accordion
6
- * with per-item conditional visibility based on triggerWhen decision strategies.
7
- *
8
- * Demonstrates the compositional action pattern where child actions
9
- * (nav:tip) serve as configuration data for the parent widget.
10
- */
11
- import { purple, slateGrey } from '@syntro/design-system/tokens';
12
- import React, { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
13
- import { createRoot } from 'react-dom/client';
14
- // ============================================================================
15
- // Emoji → Lucide SVG inline mapping (no lucide-react dependency)
16
- // ============================================================================
17
- const EMOJI_SVG_MAP = {
18
- '💵': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="12" x="2" y="6" rx="2"/><circle cx="12" cy="12" r="2"/><path d="M6 12h.01M18 12h.01"/></svg>',
19
- '🏛️': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" x2="21" y1="22" y2="22"/><line x1="6" x2="6" y1="18" y2="11"/><line x1="10" x2="10" y1="18" y2="11"/><line x1="14" x2="14" y1="18" y2="11"/><line x1="18" x2="18" y1="18" y2="11"/><polygon points="12 2 20 7 4 7"/></svg>',
20
- '⏭️': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" x2="19" y1="5" y2="19"/></svg>',
21
- '➡️': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>',
22
- '💡': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>',
23
- '💰': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="12" x="2" y="6" rx="2"/><circle cx="12" cy="12" r="2"/><path d="M6 12h.01M18 12h.01"/></svg>',
24
- '📋': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M12 11h4"/><path d="M12 16h4"/><path d="M8 11h.01"/><path d="M8 16h.01"/></svg>',
25
- '✅': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg>',
26
- '⚠️': '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>',
27
- };
28
- function renderIcon(emoji) {
29
- return EMOJI_SVG_MAP[emoji] ?? escapeHtml(emoji);
30
- }
31
- // ============================================================================
32
- // Sanitization
33
- // ============================================================================
34
- function escapeHtml(str) {
35
- return str
36
- .replace(/&/g, '&amp;')
37
- .replace(/</g, '&lt;')
38
- .replace(/>/g, '&gt;')
39
- .replace(/"/g, '&quot;')
40
- .replace(/'/g, '&#39;');
41
- }
42
- // ============================================================================
43
- // Styles
44
- // ============================================================================
45
- const baseStyles = {
46
- container: {
47
- fontFamily: 'var(--sc-font-family, system-ui, -apple-system, sans-serif)',
48
- maxWidth: '100%',
49
- overflow: 'hidden',
50
- },
51
- accordion: {
52
- display: 'flex',
53
- flexDirection: 'column',
54
- gap: 'var(--sc-content-item-gap, 6px)',
55
- },
56
- item: {
57
- borderRadius: 'var(--sc-content-border-radius, 8px)',
58
- overflow: 'hidden',
59
- transition: 'box-shadow 0.2s ease',
60
- },
61
- header: {
62
- display: 'flex',
63
- alignItems: 'center',
64
- gap: '8px',
65
- width: '100%',
66
- padding: 'var(--sc-content-item-padding, 12px 16px)',
67
- border: 'none',
68
- cursor: 'pointer',
69
- fontSize: 'var(--sc-content-item-font-size, 15px)',
70
- fontWeight: 500,
71
- fontFamily: 'inherit',
72
- textAlign: 'left',
73
- transition: 'background-color 0.15s ease',
74
- },
75
- chevron: {
76
- fontSize: '20px',
77
- transition: 'transform 0.2s ease',
78
- marginLeft: 'auto',
79
- flexShrink: 0,
80
- color: 'var(--sc-content-chevron-color, currentColor)',
81
- },
82
- icon: {
83
- fontSize: '16px',
84
- flexShrink: 0,
85
- },
86
- body: {
87
- overflow: 'hidden',
88
- transition: 'max-height 0.25s ease, padding-bottom 0.25s ease',
89
- padding: 'var(--sc-content-body-padding, 0 16px 12px 16px)',
90
- },
91
- description: {
92
- fontSize: 'var(--sc-content-body-font-size, 14px)',
93
- lineHeight: '1.5',
94
- margin: 0,
95
- },
96
- linkButton: {
97
- display: 'inline-flex',
98
- alignItems: 'center',
99
- gap: '4px',
100
- marginTop: '10px',
101
- padding: '6px 12px',
102
- borderRadius: '6px',
103
- textDecoration: 'none',
104
- fontSize: '13px',
105
- fontWeight: 500,
106
- cursor: 'pointer',
107
- border: 'none',
108
- transition: 'background-color 0.15s ease',
109
- },
110
- categoryHeader: {
111
- fontSize: 'var(--sc-content-category-font-size, 12px)',
112
- fontWeight: 600,
113
- textTransform: 'uppercase',
114
- letterSpacing: '0.05em',
115
- padding: 'var(--sc-content-category-padding, 8px 4px 4px 4px)',
116
- },
117
- emptyState: {
118
- fontSize: '13px',
119
- padding: '16px',
120
- textAlign: 'center',
121
- },
122
- };
123
- const themeStyles = {
124
- light: {
125
- container: {
126
- backgroundColor: 'transparent',
127
- color: 'inherit',
128
- },
129
- item: {
130
- backgroundColor: 'var(--sc-content-background)',
131
- border: 'var(--sc-content-border)',
132
- },
133
- itemExpanded: {
134
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.08)',
135
- },
136
- header: {
137
- backgroundColor: 'transparent',
138
- color: 'var(--sc-content-text-color)',
139
- },
140
- headerHover: {
141
- backgroundColor: 'var(--sc-content-background-hover)',
142
- },
143
- body: {
144
- color: 'var(--sc-content-text-secondary-color)',
145
- },
146
- linkButton: {
147
- backgroundColor: 'var(--sc-color-primary, #6366f1)',
148
- color: '#ffffff',
149
- },
150
- categoryHeader: {
151
- color: slateGrey[7],
152
- },
153
- emptyState: {
154
- color: slateGrey[8],
155
- },
156
- },
157
- dark: {
158
- container: {
159
- backgroundColor: 'transparent',
160
- color: 'inherit',
161
- },
162
- item: {
163
- backgroundColor: 'var(--sc-content-background)',
164
- border: 'var(--sc-content-border)',
165
- },
166
- itemExpanded: {
167
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
168
- },
169
- header: {
170
- backgroundColor: 'transparent',
171
- color: 'var(--sc-content-text-color)',
172
- },
173
- headerHover: {
174
- backgroundColor: 'var(--sc-content-background-hover)',
175
- },
176
- body: {
177
- color: 'var(--sc-content-text-secondary-color)',
178
- },
179
- linkButton: {
180
- backgroundColor: 'var(--sc-color-primary, #6366f1)',
181
- color: '#ffffff',
182
- },
183
- categoryHeader: {
184
- color: slateGrey[8],
185
- },
186
- emptyState: {
187
- color: slateGrey[7],
188
- },
189
- },
190
- };
191
- // ============================================================================
192
- // Helpers
193
- // ============================================================================
194
- /** Check if any of the given routes match the current page pathname */
195
- function routeMatchesCurrent(routes) {
196
- if (typeof window === 'undefined')
197
- return false;
198
- const current = window.location.pathname;
199
- return routes.some((route) => {
200
- // Strip query/hash from route if present
201
- const routePath = route.split('?')[0].split('#')[0];
202
- // Exact match or glob pattern (** suffix)
203
- if (routePath.endsWith('/**')) {
204
- return current.startsWith(routePath.slice(0, -3));
205
- }
206
- return current === routePath;
207
- });
208
- }
209
- /** Apply a brief pulse animation to an element, then remove it */
210
- function pulseElement(el) {
211
- const keyframes = [
212
- { boxShadow: '0 0 0 0 rgba(13, 148, 136, 0.5)' },
213
- { boxShadow: '0 0 0 8px rgba(13, 148, 136, 0)' },
214
- ];
215
- el.animate(keyframes, { duration: 600, iterations: 3, easing: 'ease-out' });
216
- }
217
- function NavTipItem({ item, isExpanded, isLast, onToggle, onNavigate, onFocusAnchor, theme, }) {
218
- const [isHovered, setIsHovered] = useState(false);
219
- const colors = themeStyles[theme];
220
- const { title, description, href, icon, external, anchor } = item.config;
221
- const itemStyle = {
222
- ...baseStyles.item,
223
- ...colors.item,
224
- ...(isExpanded ? colors.itemExpanded : {}),
225
- ...(!isLast ? { borderBottom: 'var(--sc-content-item-divider, none)' } : {}),
226
- };
227
- const headerStyle = {
228
- ...baseStyles.header,
229
- ...colors.header,
230
- ...(isHovered ? colors.headerHover : {}),
231
- };
232
- const chevronStyle = {
233
- ...baseStyles.chevron,
234
- transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)',
235
- };
236
- const bodyStyle = {
237
- ...baseStyles.body,
238
- ...colors.body,
239
- maxHeight: isExpanded ? '500px' : '0',
240
- paddingBottom: isExpanded ? '16px' : '0',
241
- };
242
- // Determine the effective navigation target from anchor or legacy href
243
- const effectiveHref = anchor
244
- ? Array.isArray(anchor.route)
245
- ? anchor.route[0]
246
- : anchor.route
247
- : href;
248
- // Same-page check: anchor exists, selector is meaningful, and route matches current page
249
- const isSamePage = anchor
250
- ? routeMatchesCurrent(Array.isArray(anchor.route) ? anchor.route : [anchor.route])
251
- : effectiveHref
252
- ? routeMatchesCurrent([effectiveHref])
253
- : false;
254
- const hasSelector = anchor?.selector && anchor.selector !== '*';
255
- const isFocusAction = isSamePage && hasSelector;
256
- const hasAction = !!effectiveHref || isFocusAction;
257
- const handleLinkClick = (e) => {
258
- e.preventDefault();
259
- e.stopPropagation();
260
- if (isFocusAction && anchor) {
261
- onFocusAnchor(anchor);
262
- }
263
- else if (effectiveHref) {
264
- onNavigate(effectiveHref, external ?? false);
265
- }
266
- };
267
- // CTA label
268
- const ctaLabel = isFocusAction ? `Focus \u2192` : external ? `Go \u2197` : `Go \u2192`;
269
- return (_jsxs("div", { style: itemStyle, "data-nav-tip-id": item.config.id, children: [_jsxs("button", { type: "button", style: headerStyle, onClick: onToggle, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), "aria-expanded": isExpanded, children: [icon && (
270
- // biome-ignore lint/security/noDangerouslySetInnerHtml: renderIcon returns sanitized SVG from EMOJI_SVG_MAP or escapeHtml
271
- _jsx("span", { style: baseStyles.icon, dangerouslySetInnerHTML: { __html: renderIcon(icon) } })), _jsx("span", { children: title }), _jsx("span", { style: chevronStyle, children: '\u203A' })] }), _jsxs("div", { style: bodyStyle, "aria-hidden": !isExpanded, children: [_jsx("p", { style: baseStyles.description, children: description }), hasAction && (_jsx("a", { href: effectiveHref || '#', onClick: handleLinkClick, style: { ...baseStyles.linkButton, ...colors.linkButton }, target: external ? '_blank' : undefined, rel: external ? 'noopener noreferrer' : undefined, children: ctaLabel }))] })] }));
272
- }
273
- // ============================================================================
274
- // NavWidget Component
275
- // ============================================================================
276
- /**
277
- * NavWidget - Renders a collapsible navigation tips accordion.
278
- *
279
- * This component demonstrates the compositional action pattern:
280
- * - Parent (NavWidget) receives `config.actions` array
281
- * - Each action has optional `triggerWhen` for per-item visibility
282
- * - Parent evaluates triggerWhen and filters visible tips
283
- * - Parent manages expand state and re-rendering on context changes
284
- */
285
- export function NavWidget({ config, runtime, instanceId }) {
286
- // Force re-render when context/accumulator changes.
287
- const [renderTick, forceUpdate] = useReducer((x) => x + 1, 0);
288
- // Track expanded tip IDs
289
- const [expandedIds, setExpandedIds] = useState(new Set());
290
- // Subscribe to context changes for reactive updates
291
- useEffect(() => {
292
- const unsubscribe = runtime.context.subscribe(() => {
293
- forceUpdate();
294
- });
295
- return unsubscribe;
296
- }, [runtime.context]);
297
- // Subscribe to accumulator changes for event_count-based triggerWhen
298
- useEffect(() => {
299
- if (!runtime.accumulator?.subscribe)
300
- return;
301
- return runtime.accumulator.subscribe(() => {
302
- forceUpdate();
303
- });
304
- }, [runtime.accumulator]);
305
- // Filter visible tips based on per-item triggerWhen
306
- // biome-ignore lint/correctness/useExhaustiveDependencies: renderTick is intentionally included to force re-evaluation when the runtime's mutable context changes (subscribed above via forceUpdate)
307
- const visibleTips = useMemo(() => config.actions.filter((tip) => {
308
- if (!tip.triggerWhen)
309
- return true;
310
- try {
311
- const result = runtime.evaluateSync(tip.triggerWhen);
312
- return result.value;
313
- }
314
- catch {
315
- // If strategy evaluation fails, hide the tip (fail-closed)
316
- return false;
317
- }
318
- }), [config.actions, runtime, renderTick]);
319
- // Group by category
320
- const categoryGroups = useMemo(() => {
321
- const groups = new Map();
322
- for (const tip of visibleTips) {
323
- const cat = tip.config.category;
324
- if (!groups.has(cat)) {
325
- groups.set(cat, []);
326
- }
327
- groups.get(cat).push(tip);
328
- }
329
- return groups;
330
- }, [visibleTips]);
331
- // Check if any items have categories
332
- const hasCategories = useMemo(() => visibleTips.some((t) => t.config.category), [visibleTips]);
333
- // Resolve theme (auto → detect system preference)
334
- const resolvedTheme = useMemo(() => {
335
- if (config.theme && config.theme !== 'auto')
336
- return config.theme;
337
- if (typeof window !== 'undefined') {
338
- return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
339
- }
340
- return 'light';
341
- }, [config.theme]);
342
- // Handle tip toggle
343
- const handleToggle = useCallback((id) => {
344
- setExpandedIds((prev) => {
345
- const wasExpanded = prev.has(id);
346
- let next;
347
- if (config.expandBehavior === 'single') {
348
- // In single mode, emit collapse events for any previously-expanded tips
349
- for (const prevId of prev) {
350
- if (prevId !== id) {
351
- runtime.events.publish('nav:toggled', {
352
- instanceId,
353
- tipId: prevId,
354
- expanded: false,
355
- timestamp: Date.now(),
356
- });
357
- }
358
- }
359
- next = wasExpanded ? new Set() : new Set([id]);
360
- }
361
- else {
362
- next = new Set(prev);
363
- if (wasExpanded) {
364
- next.delete(id);
365
- }
366
- else {
367
- next.add(id);
368
- }
369
- }
370
- // Emit event for the clicked tip using fresh state from the updater
371
- runtime.events.publish('nav:toggled', {
372
- instanceId,
373
- tipId: id,
374
- expanded: !wasExpanded,
375
- timestamp: Date.now(),
376
- });
377
- return next;
378
- });
379
- }, [config.expandBehavior, runtime.events, instanceId]);
380
- // Handle navigation with event publishing
381
- const handleNavigate = useCallback((href, external) => {
382
- // Reject dangerous URIs to prevent XSS
383
- const normalizedHref = href.trim().toLowerCase();
384
- if (normalizedHref.startsWith('javascript:') || normalizedHref.startsWith('data:')) {
385
- return;
386
- }
387
- runtime.events.publish('nav:tip_clicked', {
388
- instanceId,
389
- href,
390
- external,
391
- timestamp: Date.now(),
392
- });
393
- if (external) {
394
- window.open(href, '_blank', 'noopener,noreferrer');
395
- }
396
- else {
397
- // SPA navigation: pushState updates the URL, then popstate tells the
398
- // host app's router (e.g. React Router) to render the new page.
399
- // Cleanup functions in revertAll() are resilient to detached DOM nodes,
400
- // so no timing hack is needed between pushState and popstate.
401
- const url = new URL(href, window.location.origin);
402
- url.search = window.location.search;
403
- window.history.pushState(null, '', url.toString());
404
- window.dispatchEvent(new PopStateEvent('popstate'));
405
- }
406
- }, [runtime.events, instanceId]);
407
- // Handle same-page anchor focus: scroll + pulse + focus
408
- const handleFocusAnchor = useCallback((anchor) => {
409
- const el = document.querySelector(anchor.selector);
410
- if (!(el instanceof HTMLElement))
411
- return;
412
- runtime.events.publish('nav:tip_focused', {
413
- instanceId,
414
- selector: anchor.selector,
415
- route: anchor.route,
416
- timestamp: Date.now(),
417
- });
418
- el.scrollIntoView({ behavior: 'smooth', block: 'center' });
419
- pulseElement(el);
420
- // Focus after scroll completes
421
- setTimeout(() => el.focus(), 400);
422
- }, [runtime.events, instanceId]);
423
- // Compute container styles
424
- const containerStyle = {
425
- ...baseStyles.container,
426
- ...themeStyles[resolvedTheme].container,
427
- };
428
- const categoryHeaderStyle = {
429
- ...baseStyles.categoryHeader,
430
- ...themeStyles[resolvedTheme].categoryHeader,
431
- };
432
- const emptyStateStyle = {
433
- ...baseStyles.emptyState,
434
- ...themeStyles[resolvedTheme].emptyState,
435
- };
436
- // Render a list of nav tip items
437
- const renderItems = (items) => items.map((tip, index) => (_jsx(NavTipItem, { item: tip, isExpanded: expandedIds.has(tip.config.id), isLast: index === items.length - 1, onToggle: () => handleToggle(tip.config.id), onNavigate: handleNavigate, onFocusAnchor: handleFocusAnchor, theme: resolvedTheme }, tip.config.id)));
438
- // Empty state
439
- if (visibleTips.length === 0) {
440
- return (_jsx("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: _jsx("div", { style: emptyStateStyle, children: "You're all set for now! We'll share helpful tips here when they're relevant to what you're doing." }) }));
441
- }
442
- return (_jsx("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: _jsx("div", { style: baseStyles.accordion, children: hasCategories
443
- ? Array.from(categoryGroups.entries()).map(([category, items]) => (_jsxs(React.Fragment, { children: [category && (_jsx("div", { style: categoryHeaderStyle, "data-category-header": category, children: category })), renderItems(items)] }, category ?? '__ungrouped')))
444
- : renderItems(visibleTips) }) }));
445
- }
446
- // ============================================================================
447
- // Mountable Widget Interface
448
- // ============================================================================
449
- /**
450
- * Mountable widget interface for the runtime's WidgetRegistry.
451
- */
452
- export const NavMountableWidget = {
453
- mount(container, config) {
454
- const { runtime, instanceId = 'nav-widget', ...navConfig } = config || {
455
- expandBehavior: 'single',
456
- theme: 'auto',
457
- actions: [],
458
- };
459
- // React rendering when runtime + ReactDOM are available
460
- if (runtime && typeof createRoot === 'function') {
461
- const root = createRoot(container);
462
- root.render(React.createElement(NavWidget, {
463
- config: navConfig,
464
- runtime: runtime,
465
- instanceId,
466
- }));
467
- return () => {
468
- root.unmount();
469
- };
470
- }
471
- // HTML fallback for non-React environments
472
- const tips = navConfig.actions || [];
473
- container.innerHTML = `
474
- <div style="font-family: system-ui; max-width: 100%;">
475
- ${tips
476
- .map((tip) => `
477
- <div style="margin-bottom: 4px; padding: 12px 16px; background: ${slateGrey[12]}; border-radius: 8px;">
478
- ${tip.config.icon ? `<span>${renderIcon(tip.config.icon)}</span> ` : ''}<strong>${escapeHtml(tip.config.title)}</strong>
479
- <p style="margin-top: 8px; color: ${slateGrey[6]}; font-size: 13px;">${escapeHtml(tip.config.description)}</p>
480
- ${tip.config.href ? `<a href="${escapeHtml(tip.config.href)}" style="color: ${purple[2]}; font-size: 13px;">Go &rarr;</a>` : ''}
481
- </div>
482
- `)
483
- .join('')}
484
- </div>
485
- `;
486
- return () => {
487
- container.innerHTML = '';
488
- };
489
- },
490
- };
491
- export default NavWidget;
package/dist/cdn.d.ts DELETED
@@ -1,62 +0,0 @@
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 NavEditor from './editor';
8
- /**
9
- * App manifest for registry registration.
10
- * Follows the AppManifest interface expected by AppLoader/AppRegistry.
11
- */
12
- export declare const manifest: {
13
- id: string;
14
- version: string;
15
- name: string;
16
- description: string;
17
- runtime: {
18
- actions: {
19
- kind: "navigation:scrollTo" | "navigation:navigate";
20
- executor: import("packages/sdk-contracts/dist").ActionExecutor<import("./types").ScrollToAction> | import("packages/sdk-contracts/dist").ActionExecutor<import("./types").NavigateAction>;
21
- }[];
22
- widgets: {
23
- id: string;
24
- component: {
25
- mount(container: HTMLElement, config?: import("./types").NavConfig & {
26
- runtime?: import("./types").NavWidgetRuntime;
27
- instanceId?: string;
28
- }): () => void;
29
- };
30
- metadata: {
31
- name: string;
32
- description: string;
33
- icon: string;
34
- };
35
- }[];
36
- notifyWatchers: (props: Record<string, unknown>) => {
37
- id: string;
38
- strategy: import("./types").DecisionStrategy<boolean>;
39
- eventName: string;
40
- eventProps: {
41
- tipId: string;
42
- title: string | undefined;
43
- body: string | undefined;
44
- icon: string | undefined;
45
- };
46
- }[];
47
- };
48
- editor: {
49
- component: typeof NavEditor;
50
- panel: {
51
- title: string;
52
- icon: string;
53
- description: string;
54
- };
55
- getActionLabel(action: Record<string, unknown>): string;
56
- };
57
- metadata: {
58
- isBuiltIn: boolean;
59
- };
60
- };
61
- export default manifest;
62
- //# sourceMappingURL=cdn.d.ts.map
package/dist/cdn.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,SAA0B,MAAM,UAAU,CAAC;AAGlD;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;2BAsCgmmB,CAAC;8BAA8B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAtB1nmB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;CAQjD,CAAC;AAaF,eAAe,QAAQ,CAAC"}
package/dist/cdn.js DELETED
@@ -1,48 +0,0 @@
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 NavEditor, { editorPanel } from './editor';
8
- import { executors, runtime } from './runtime';
9
- /**
10
- * App manifest for registry registration.
11
- * Follows the AppManifest interface expected by AppLoader/AppRegistry.
12
- */
13
- export const manifest = {
14
- id: 'adaptive-nav',
15
- version: runtime.version,
16
- name: runtime.name,
17
- description: runtime.description,
18
- runtime: {
19
- actions: executors.map(({ kind, executor }) => ({
20
- kind,
21
- executor,
22
- })),
23
- widgets: runtime.widgets,
24
- notifyWatchers: runtime.notifyWatchers,
25
- },
26
- editor: {
27
- component: NavEditor,
28
- panel: editorPanel,
29
- getActionLabel(action) {
30
- const config = action.config || {};
31
- return config.title || action.kind || 'nav:tip';
32
- },
33
- },
34
- metadata: {
35
- isBuiltIn: false,
36
- },
37
- };
38
- /**
39
- * Self-register with global registry if available.
40
- * This happens when loaded via script tag (UMD).
41
- */
42
- if (typeof window !== 'undefined') {
43
- const registry = window.SynOS?.appRegistry;
44
- if (registry && typeof registry.register === 'function') {
45
- registry.register(manifest);
46
- }
47
- }
48
- export default manifest;
package/dist/summarize.js DELETED
@@ -1,51 +0,0 @@
1
- /**
2
- * Human-readable summary generation for Nav items.
3
- * Pure functions — no DOM access, just string formatting.
4
- */
5
- const MAX_TITLE_LEN = 30;
6
- function truncate(text, max) {
7
- if (text.length <= max)
8
- return text;
9
- return `${text.slice(0, max).trimEnd()}...`;
10
- }
11
- function isRuleStrategy(s) {
12
- return (typeof s === 'object' &&
13
- s !== null &&
14
- s.type === 'rules' &&
15
- Array.isArray(s.rules));
16
- }
17
- /**
18
- * Parse a triggerWhen strategy into a human-readable trigger description.
19
- */
20
- export function describeTrigger(triggerWhen) {
21
- if (!triggerWhen)
22
- return 'All pages';
23
- if (!isRuleStrategy(triggerWhen))
24
- return 'All pages';
25
- const pages = [];
26
- const anchors = [];
27
- for (const rule of triggerWhen.rules) {
28
- for (const condition of rule.conditions) {
29
- if (condition.type === 'page_url' && typeof condition.url === 'string') {
30
- pages.push(condition.url);
31
- }
32
- if (condition.type === 'anchor_visible' && typeof condition.anchorId === 'string') {
33
- anchors.push(condition.anchorId);
34
- }
35
- }
36
- }
37
- const parts = [];
38
- if (pages.length > 0)
39
- parts.push(pages[0]);
40
- if (anchors.length > 0)
41
- parts.push(anchors[0]);
42
- return parts.length > 0 ? parts.join(' \u00b7 ') : 'All pages';
43
- }
44
- /**
45
- * Generate a one-liner summary for a Nav tip.
46
- */
47
- export function summarizeNavItem(item) {
48
- const icon = item.config.icon || '\u{1F9ED}';
49
- const title = truncate(item.config.title, MAX_TITLE_LEN);
50
- return `${icon} ${title}`;
51
- }
package/dist/types.js DELETED
@@ -1,18 +0,0 @@
1
- /**
2
- * Adaptive Nav - Types
3
- *
4
- * Type definitions for the navigation tips accordion adaptive.
5
- * Demonstrates compositional action pattern with per-item triggerWhen.
6
- */
7
- // ============================================================================
8
- // Action Namespace
9
- // ============================================================================
10
- export const ACTION_NAMESPACES = ['nav', 'navigation'];
11
- /**
12
- * Returns true if the action belongs to this adaptive package.
13
- * Uses prefix matching so new kinds (e.g. nav:dropdown) are automatically included.
14
- * Covers both `nav:*` (compositional) and `navigation:*` (executor) prefixes.
15
- */
16
- export function isOwnAction(action) {
17
- return ACTION_NAMESPACES.some((ns) => action.kind.startsWith(`${ns}:`));
18
- }