@syntrologie/adapt-nav 2.1.0 → 2.2.0-canary.2
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/NavWidget.d.ts +1 -1
- package/dist/NavWidget.d.ts.map +1 -1
- package/dist/NavWidget.js +6 -8
- package/dist/cdn.d.ts +1 -1
- package/dist/cdn.d.ts.map +1 -1
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +35 -10
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/schema.d.ts +702 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +33 -0
- package/dist/summarize.d.ts +1 -1
- package/dist/summarize.d.ts.map +1 -1
- package/dist/types.d.ts +5 -15
- package/dist/types.d.ts.map +1 -1
- package/node_modules/@syntro/design-system/README.md +335 -0
- package/node_modules/@syntro/design-system/dist/assets/syntrologie-logo.svg +21 -0
- package/node_modules/@syntro/design-system/dist/assets/syntrologie-logomark.svg +10 -0
- package/node_modules/@syntro/design-system/dist/index.d.ts +8 -0
- package/node_modules/@syntro/design-system/dist/index.d.ts.map +1 -0
- package/node_modules/@syntro/design-system/dist/index.js +7 -0
- package/node_modules/@syntro/design-system/dist/tailwind-preset.d.ts +19 -0
- package/node_modules/@syntro/design-system/dist/tailwind-preset.d.ts.map +1 -0
- package/node_modules/@syntro/design-system/dist/tailwind-preset.js +432 -0
- package/node_modules/@syntro/design-system/dist/tokens/colors.css +464 -0
- package/node_modules/@syntro/design-system/dist/tokens/colors.d.ts +874 -0
- package/node_modules/@syntro/design-system/dist/tokens/colors.d.ts.map +1 -0
- package/node_modules/@syntro/design-system/dist/tokens/colors.js +564 -0
- package/node_modules/@syntro/design-system/dist/tokens/effects.css +43 -0
- package/node_modules/@syntro/design-system/dist/tokens/effects.d.ts +85 -0
- package/node_modules/@syntro/design-system/dist/tokens/effects.d.ts.map +1 -0
- package/node_modules/@syntro/design-system/dist/tokens/effects.js +77 -0
- package/node_modules/@syntro/design-system/dist/tokens/index.d.ts +10 -0
- package/node_modules/@syntro/design-system/dist/tokens/index.d.ts.map +1 -0
- package/node_modules/@syntro/design-system/dist/tokens/index.js +9 -0
- package/node_modules/@syntro/design-system/package.json +55 -0
- package/node_modules/@syntro/design-system/src/assets/syntrologie-logo.svg +21 -0
- package/node_modules/@syntro/design-system/src/assets/syntrologie-logomark.svg +10 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/BeforeAfterToggle.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/BeforeAfterToggle.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/BeforeAfterToggle.test.js +28 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DetectionBadge.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DetectionBadge.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DetectionBadge.test.js +18 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DismissedSection.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DismissedSection.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DismissedSection.test.js +22 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditBackButton.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditBackButton.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditBackButton.test.js +20 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorBody.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorBody.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorBody.test.js +12 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorCard.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorCard.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorCard.test.js +25 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorFooter.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorFooter.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorFooter.test.js +23 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorHeader.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorHeader.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorHeader.test.js +24 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorInput.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorInput.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorInput.test.js +26 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorLayout.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorLayout.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorLayout.test.js +13 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorSelect.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorSelect.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorSelect.test.js +22 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorTextarea.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorTextarea.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorTextarea.test.js +20 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ElementHighlight.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ElementHighlight.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ElementHighlight.test.js +100 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EmptyState.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EmptyState.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EmptyState.test.js +10 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/GroupHeader.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/GroupHeader.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/GroupHeader.test.js +14 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/TriggerJourney.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/TriggerJourney.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/TriggerJourney.test.js +126 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/cn.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/cn.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/cn.test.js +16 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/formatConditionLabel.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/formatConditionLabel.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/formatConditionLabel.test.js +329 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useElementRect.test.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useElementRect.test.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useElementRect.test.js +112 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts +2 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/cn.js +3 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts +31 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.js +152 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.js +9 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts +23 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.js +40 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts +6 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.js +5 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts +8 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.js +9 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.js +4 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.js +4 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts +13 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.js +6 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.js +4 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts +9 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.js +4 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts +8 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.js +5 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts +7 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.js +4 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts +23 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.js +116 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts +8 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.js +5 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts +8 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.js +15 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts +32 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.js +75 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts +6 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.js +4 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts +8 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.js +5 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts +12 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.js +40 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts +26 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.js +207 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts +8 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.js +46 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useShowWhenStatus.d.ts +24 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useShowWhenStatus.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useShowWhenStatus.js +215 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts +33 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/index.js +24 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts +22 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts.map +1 -0
- package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.js +143 -0
- package/node_modules/@syntrologie/shared-editor-ui/package.json +45 -0
- package/package.json +15 -10
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a live DOMRect for an element, updating on scroll, resize,
|
|
4
|
+
* and element size changes.
|
|
5
|
+
*
|
|
6
|
+
* Uses requestAnimationFrame to batch updates and avoid layout thrashing.
|
|
7
|
+
*/
|
|
8
|
+
export function useElementRect(element) {
|
|
9
|
+
const [rect, setRect] = useState(null);
|
|
10
|
+
const update = useCallback(() => {
|
|
11
|
+
if (element) {
|
|
12
|
+
setRect(element.getBoundingClientRect());
|
|
13
|
+
}
|
|
14
|
+
}, [element]);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!element) {
|
|
17
|
+
setRect(null);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// Initial measurement
|
|
21
|
+
setRect(element.getBoundingClientRect());
|
|
22
|
+
let rafId = null;
|
|
23
|
+
const scheduleUpdate = () => {
|
|
24
|
+
if (rafId != null)
|
|
25
|
+
return;
|
|
26
|
+
rafId = requestAnimationFrame(() => {
|
|
27
|
+
rafId = null;
|
|
28
|
+
update();
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
// Scroll (capture phase catches nested scroll containers)
|
|
32
|
+
window.addEventListener('scroll', scheduleUpdate, true);
|
|
33
|
+
window.addEventListener('resize', scheduleUpdate);
|
|
34
|
+
// Observe element size changes
|
|
35
|
+
const ro = new ResizeObserver(scheduleUpdate);
|
|
36
|
+
ro.observe(element);
|
|
37
|
+
return () => {
|
|
38
|
+
window.removeEventListener('scroll', scheduleUpdate, true);
|
|
39
|
+
window.removeEventListener('resize', scheduleUpdate);
|
|
40
|
+
ro.disconnect();
|
|
41
|
+
if (rafId != null)
|
|
42
|
+
cancelAnimationFrame(rafId);
|
|
43
|
+
};
|
|
44
|
+
}, [element, update]);
|
|
45
|
+
return rect;
|
|
46
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ShowWhenStatus } from '../components/ConditionStatusLine';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal type for a showWhen action item.
|
|
4
|
+
* Works with both FAQQuestionAction and NavTipAction.
|
|
5
|
+
*/
|
|
6
|
+
export interface ShowWhenItem {
|
|
7
|
+
id: string;
|
|
8
|
+
showWhen?: {
|
|
9
|
+
type: string;
|
|
10
|
+
rules?: Array<{
|
|
11
|
+
conditions: Array<Record<string, unknown>>;
|
|
12
|
+
value: unknown;
|
|
13
|
+
}>;
|
|
14
|
+
default?: unknown;
|
|
15
|
+
} | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook: live showWhen evaluation for a list of action items.
|
|
19
|
+
*
|
|
20
|
+
* @param items Array of items with id + optional showWhen
|
|
21
|
+
* @returns Map from item id → ShowWhenStatus (null for items without showWhen)
|
|
22
|
+
*/
|
|
23
|
+
export declare function useShowWhenStatus(items: ShowWhenItem[]): Map<string, ShowWhenStatus | null>;
|
|
24
|
+
//# sourceMappingURL=useShowWhenStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShowWhenStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useShowWhenStatus.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGzF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,KAAK,CAAC;YACZ,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3C,KAAK,EAAE,OAAO,CAAC;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,GAAG,IAAI,CAAC;CACV;AAuND;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC,CA0C3F"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useShowWhenStatus — live showWhen evaluation for editor diagnostics.
|
|
3
|
+
*
|
|
4
|
+
* Subscribes to the runtime's EventAccumulator for reactive updates.
|
|
5
|
+
* Evaluates each item's showWhen strategy locally to get
|
|
6
|
+
* per-condition breakdowns.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This hook accesses `window.SynOS.handle.runtime` directly
|
|
9
|
+
* because EditorPanelProps doesn't expose runtime. This is safe —
|
|
10
|
+
* the editor only runs after runtime bootstrap.
|
|
11
|
+
*/
|
|
12
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
13
|
+
import { formatConditionLabel } from '../formatConditionLabel';
|
|
14
|
+
function getRuntime() {
|
|
15
|
+
return window.SynOS?.handle?.runtime ?? null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Evaluate a single condition against the runtime context.
|
|
19
|
+
*/
|
|
20
|
+
function evaluateConditionLocally(condition, runtime) {
|
|
21
|
+
const ctx = runtime.context.get();
|
|
22
|
+
const type = condition.type;
|
|
23
|
+
let passed = false;
|
|
24
|
+
let accCount;
|
|
25
|
+
switch (type) {
|
|
26
|
+
case 'event_count': {
|
|
27
|
+
if (!runtime.accumulator)
|
|
28
|
+
break;
|
|
29
|
+
const key = condition.key;
|
|
30
|
+
const withinMs = condition.withinMs;
|
|
31
|
+
const count = runtime.accumulator.getCount(key, withinMs);
|
|
32
|
+
accCount = count;
|
|
33
|
+
const target = condition.count;
|
|
34
|
+
const op = condition.operator;
|
|
35
|
+
switch (op) {
|
|
36
|
+
case 'gte':
|
|
37
|
+
passed = count >= target;
|
|
38
|
+
break;
|
|
39
|
+
case 'lte':
|
|
40
|
+
passed = count <= target;
|
|
41
|
+
break;
|
|
42
|
+
case 'eq':
|
|
43
|
+
passed = count === target;
|
|
44
|
+
break;
|
|
45
|
+
case 'gt':
|
|
46
|
+
passed = count > target;
|
|
47
|
+
break;
|
|
48
|
+
case 'lt':
|
|
49
|
+
passed = count < target;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'page_url': {
|
|
55
|
+
const url = condition.url;
|
|
56
|
+
const pattern = url
|
|
57
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
58
|
+
.replace(/\*\*/g, '.*')
|
|
59
|
+
.replace(/\*/g, '[^/]*');
|
|
60
|
+
passed = new RegExp(`^${pattern}$`).test(ctx.page.url);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'route':
|
|
64
|
+
passed = ctx.page.routeId === condition.routeId;
|
|
65
|
+
break;
|
|
66
|
+
case 'anchor_visible': {
|
|
67
|
+
const anchors = ctx.anchors;
|
|
68
|
+
const anchor = anchors?.find((a) => a.anchorId === condition.anchorId);
|
|
69
|
+
switch (condition.state) {
|
|
70
|
+
case 'visible':
|
|
71
|
+
passed = anchor?.visible === true;
|
|
72
|
+
break;
|
|
73
|
+
case 'present':
|
|
74
|
+
passed = anchor?.present === true;
|
|
75
|
+
break;
|
|
76
|
+
case 'absent':
|
|
77
|
+
passed = !anchor?.present;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case 'event_occurred':
|
|
83
|
+
passed =
|
|
84
|
+
runtime.events?.hasRecentEvent(condition.eventName, condition.withinMs ?? 60000) ?? false;
|
|
85
|
+
break;
|
|
86
|
+
case 'viewport': {
|
|
87
|
+
const { width, height } = ctx.viewport;
|
|
88
|
+
passed = true;
|
|
89
|
+
if (condition.minWidth !== undefined && width < condition.minWidth)
|
|
90
|
+
passed = false;
|
|
91
|
+
if (condition.maxWidth !== undefined && width > condition.maxWidth)
|
|
92
|
+
passed = false;
|
|
93
|
+
if (condition.minHeight !== undefined && height < condition.minHeight)
|
|
94
|
+
passed = false;
|
|
95
|
+
if (condition.maxHeight !== undefined && height > condition.maxHeight)
|
|
96
|
+
passed = false;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'session_metric': {
|
|
100
|
+
const val = runtime.state?.getSessionMetric(condition.key) ?? 0;
|
|
101
|
+
const threshold = condition.threshold;
|
|
102
|
+
const op = condition.operator;
|
|
103
|
+
switch (op) {
|
|
104
|
+
case 'gte':
|
|
105
|
+
passed = val >= threshold;
|
|
106
|
+
break;
|
|
107
|
+
case 'lte':
|
|
108
|
+
passed = val <= threshold;
|
|
109
|
+
break;
|
|
110
|
+
case 'eq':
|
|
111
|
+
passed = val === threshold;
|
|
112
|
+
break;
|
|
113
|
+
case 'gt':
|
|
114
|
+
passed = val > threshold;
|
|
115
|
+
break;
|
|
116
|
+
case 'lt':
|
|
117
|
+
passed = val < threshold;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case 'dismissed':
|
|
123
|
+
passed = condition.inverted
|
|
124
|
+
? !(runtime.state?.isDismissed(condition.key) ?? false)
|
|
125
|
+
: (runtime.state?.isDismissed(condition.key) ?? false);
|
|
126
|
+
break;
|
|
127
|
+
case 'cooldown_active':
|
|
128
|
+
passed = condition.inverted
|
|
129
|
+
? !(runtime.state?.isCooldownActive(condition.key) ?? false)
|
|
130
|
+
: (runtime.state?.isCooldownActive(condition.key) ?? false);
|
|
131
|
+
break;
|
|
132
|
+
case 'frequency_limit': {
|
|
133
|
+
const count = runtime.state?.getFrequencyCount(condition.key) ?? 0;
|
|
134
|
+
const limitReached = count >= condition.limit;
|
|
135
|
+
passed = condition.inverted ? !limitReached : limitReached;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const formatted = formatConditionLabel(condition, accCount);
|
|
140
|
+
return {
|
|
141
|
+
passed,
|
|
142
|
+
cs: { type, passed, formatted },
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Evaluate all conditions in a showWhen RuleStrategy.
|
|
147
|
+
*/
|
|
148
|
+
function evaluateShowWhen(showWhen, runtime) {
|
|
149
|
+
if (showWhen.type !== 'rules' || !showWhen.rules?.length) {
|
|
150
|
+
return { visible: !!showWhen.default, isFallback: true, conditions: [] };
|
|
151
|
+
}
|
|
152
|
+
// Evaluate ALL rules' conditions for diagnostic display
|
|
153
|
+
const allConditions = [];
|
|
154
|
+
for (const rule of showWhen.rules) {
|
|
155
|
+
let ruleMatched = true;
|
|
156
|
+
for (const condition of rule.conditions) {
|
|
157
|
+
const { passed, cs } = evaluateConditionLocally(condition, runtime);
|
|
158
|
+
allConditions.push(cs);
|
|
159
|
+
if (!passed)
|
|
160
|
+
ruleMatched = false;
|
|
161
|
+
}
|
|
162
|
+
if (ruleMatched) {
|
|
163
|
+
return { visible: rule.value, isFallback: false, conditions: allConditions };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// No rules matched — use default
|
|
167
|
+
return {
|
|
168
|
+
visible: showWhen.default ?? false,
|
|
169
|
+
isFallback: true,
|
|
170
|
+
conditions: allConditions,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Hook: live showWhen evaluation for a list of action items.
|
|
175
|
+
*
|
|
176
|
+
* @param items Array of items with id + optional showWhen
|
|
177
|
+
* @returns Map from item id → ShowWhenStatus (null for items without showWhen)
|
|
178
|
+
*/
|
|
179
|
+
export function useShowWhenStatus(items) {
|
|
180
|
+
const [statuses, setStatuses] = useState(new Map());
|
|
181
|
+
const itemsRef = useRef(items);
|
|
182
|
+
itemsRef.current = items;
|
|
183
|
+
const evaluate = useCallback(() => {
|
|
184
|
+
const runtime = getRuntime();
|
|
185
|
+
if (!runtime)
|
|
186
|
+
return;
|
|
187
|
+
const map = new Map();
|
|
188
|
+
for (const item of itemsRef.current) {
|
|
189
|
+
if (!item.showWhen) {
|
|
190
|
+
map.set(item.id, null);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
map.set(item.id, evaluateShowWhen(item.showWhen, runtime));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
setStatuses(map);
|
|
197
|
+
}, []);
|
|
198
|
+
useEffect(() => {
|
|
199
|
+
// Initial evaluation
|
|
200
|
+
evaluate();
|
|
201
|
+
// Subscribe to accumulator changes for reactive event_count updates
|
|
202
|
+
const runtime = getRuntime();
|
|
203
|
+
const unsubs = [];
|
|
204
|
+
if (runtime?.accumulator) {
|
|
205
|
+
unsubs.push(runtime.accumulator.subscribe(evaluate));
|
|
206
|
+
}
|
|
207
|
+
// Poll every 2s for non-accumulator conditions (page_url, viewport, etc.)
|
|
208
|
+
const interval = setInterval(evaluate, 2000);
|
|
209
|
+
return () => {
|
|
210
|
+
unsubs.forEach((u) => u());
|
|
211
|
+
clearInterval(interval);
|
|
212
|
+
};
|
|
213
|
+
}, [evaluate]);
|
|
214
|
+
return statuses;
|
|
215
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export { cn } from './cn';
|
|
2
|
+
export type { AnchorPickerProps, PickedElement } from './components/AnchorPicker';
|
|
3
|
+
export { AnchorPicker } from './components/AnchorPicker';
|
|
4
|
+
export { BeforeAfterToggle } from './components/BeforeAfterToggle';
|
|
5
|
+
export type { ConditionStatus, ShowWhenStatus } from './components/ConditionStatusLine';
|
|
6
|
+
export { ConditionStatusLine } from './components/ConditionStatusLine';
|
|
7
|
+
export { DetectionBadge } from './components/DetectionBadge';
|
|
8
|
+
export { DismissedSection } from './components/DismissedSection';
|
|
9
|
+
export { EditBackButton } from './components/EditBackButton';
|
|
10
|
+
export { EditorBody } from './components/EditorBody';
|
|
11
|
+
export { EditorCard } from './components/EditorCard';
|
|
12
|
+
export { EditorFooter } from './components/EditorFooter';
|
|
13
|
+
export { EditorHeader } from './components/EditorHeader';
|
|
14
|
+
export { EditorInput } from './components/EditorInput';
|
|
15
|
+
export { EditorLayout } from './components/EditorLayout';
|
|
16
|
+
export type { EditorPanelShellProps } from './components/EditorPanelShell';
|
|
17
|
+
export { EditorPanelShell } from './components/EditorPanelShell';
|
|
18
|
+
export { EditorSelect } from './components/EditorSelect';
|
|
19
|
+
export { EditorTextarea } from './components/EditorTextarea';
|
|
20
|
+
export type { ElementHighlightProps } from './components/ElementHighlight';
|
|
21
|
+
export { ElementHighlight } from './components/ElementHighlight';
|
|
22
|
+
export { EmptyState } from './components/EmptyState';
|
|
23
|
+
export type { TriggerJourneyProps } from './components/TriggerJourney';
|
|
24
|
+
export { TriggerJourney } from './components/TriggerJourney';
|
|
25
|
+
export { GroupHeader } from './components/GroupHeader';
|
|
26
|
+
export type { ConditionProgress, FormattedCondition } from './formatConditionLabel';
|
|
27
|
+
export { formatConditionLabel } from './formatConditionLabel';
|
|
28
|
+
export { useElementRect } from './hooks/useElementRect';
|
|
29
|
+
export type { ShowWhenItem } from './hooks/useShowWhenStatus';
|
|
30
|
+
export { useShowWhenStatus } from './hooks/useShowWhenStatus';
|
|
31
|
+
export type { SelectorOptions } from './utils/selectorGenerator';
|
|
32
|
+
export { generateSelector, getElementDescription, validateSelector, } from './utils/selectorGenerator';
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC1B,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export { cn } from './cn';
|
|
2
|
+
export { AnchorPicker } from './components/AnchorPicker';
|
|
3
|
+
export { BeforeAfterToggle } from './components/BeforeAfterToggle';
|
|
4
|
+
export { ConditionStatusLine } from './components/ConditionStatusLine';
|
|
5
|
+
export { DetectionBadge } from './components/DetectionBadge';
|
|
6
|
+
export { DismissedSection } from './components/DismissedSection';
|
|
7
|
+
export { EditBackButton } from './components/EditBackButton';
|
|
8
|
+
export { EditorBody } from './components/EditorBody';
|
|
9
|
+
export { EditorCard } from './components/EditorCard';
|
|
10
|
+
export { EditorFooter } from './components/EditorFooter';
|
|
11
|
+
export { EditorHeader } from './components/EditorHeader';
|
|
12
|
+
export { EditorInput } from './components/EditorInput';
|
|
13
|
+
export { EditorLayout } from './components/EditorLayout';
|
|
14
|
+
export { EditorPanelShell } from './components/EditorPanelShell';
|
|
15
|
+
export { EditorSelect } from './components/EditorSelect';
|
|
16
|
+
export { EditorTextarea } from './components/EditorTextarea';
|
|
17
|
+
export { ElementHighlight } from './components/ElementHighlight';
|
|
18
|
+
export { EmptyState } from './components/EmptyState';
|
|
19
|
+
export { TriggerJourney } from './components/TriggerJourney';
|
|
20
|
+
export { GroupHeader } from './components/GroupHeader';
|
|
21
|
+
export { formatConditionLabel } from './formatConditionLabel';
|
|
22
|
+
export { useElementRect } from './hooks/useElementRect';
|
|
23
|
+
export { useShowWhenStatus } from './hooks/useShowWhenStatus';
|
|
24
|
+
export { generateSelector, getElementDescription, validateSelector, } from './utils/selectorGenerator';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface SelectorOptions {
|
|
2
|
+
includeTag?: boolean;
|
|
3
|
+
preferTestIds?: boolean;
|
|
4
|
+
maxCombinations?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Generates a CSS selector for a given DOM element.
|
|
8
|
+
* Uses css-selector-generator with settings optimized for:
|
|
9
|
+
* - Stability (prefers IDs, data-testid, stable classes)
|
|
10
|
+
* - Readability (includes tag names)
|
|
11
|
+
* - Uniqueness (generates unique selectors)
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateSelector(element: Element, options?: SelectorOptions): string;
|
|
14
|
+
/**
|
|
15
|
+
* Validates that a selector correctly targets the expected element.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateSelector(selector: string, expectedElement: Element): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Gets a human-readable description of an element for UI display.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getElementDescription(element: Element): string;
|
|
22
|
+
//# sourceMappingURL=selectorGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectorGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/selectorGenerator.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CAiExF;AAmCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,GAAG,OAAO,CAOpF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAiB9D"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { getCssSelector } from 'css-selector-generator';
|
|
2
|
+
const DEFAULT_OPTIONS = {
|
|
3
|
+
includeTag: true,
|
|
4
|
+
preferTestIds: true,
|
|
5
|
+
maxCombinations: 100,
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Generates a CSS selector for a given DOM element.
|
|
9
|
+
* Uses css-selector-generator with settings optimized for:
|
|
10
|
+
* - Stability (prefers IDs, data-testid, stable classes)
|
|
11
|
+
* - Readability (includes tag names)
|
|
12
|
+
* - Uniqueness (generates unique selectors)
|
|
13
|
+
*/
|
|
14
|
+
export function generateSelector(element, options = {}) {
|
|
15
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
16
|
+
// Build selector types in priority order
|
|
17
|
+
const selectors = [];
|
|
18
|
+
// Always prioritize ID if available
|
|
19
|
+
selectors.push('id');
|
|
20
|
+
// Include data-testid and other stable attributes
|
|
21
|
+
if (opts.preferTestIds) {
|
|
22
|
+
selectors.push('attribute');
|
|
23
|
+
}
|
|
24
|
+
// Then class names (filtered to exclude dynamic ones)
|
|
25
|
+
selectors.push('class');
|
|
26
|
+
// Tag names for context
|
|
27
|
+
selectors.push('tag');
|
|
28
|
+
// Fallbacks for uniqueness
|
|
29
|
+
selectors.push('nthchild');
|
|
30
|
+
selectors.push('nthoftype');
|
|
31
|
+
try {
|
|
32
|
+
const selector = getCssSelector(element, {
|
|
33
|
+
selectors,
|
|
34
|
+
includeTag: opts.includeTag,
|
|
35
|
+
maxCombinations: opts.maxCombinations,
|
|
36
|
+
// Blacklist common dynamic class patterns
|
|
37
|
+
blacklist: [
|
|
38
|
+
// Dynamic class patterns
|
|
39
|
+
/^[a-z]+-[a-f0-9]{5,}$/i, // hash-based classes like "css-1abc23"
|
|
40
|
+
/^_[a-zA-Z0-9]+$/, // CSS module classes like "_1abc23"
|
|
41
|
+
/^svelte-[a-z0-9]+$/i, // Svelte scoped classes
|
|
42
|
+
/^vue-[a-z0-9]+$/i, // Vue scoped classes
|
|
43
|
+
/^emotion-[0-9]+$/, // Emotion CSS-in-JS
|
|
44
|
+
/^sc-[a-zA-Z]+$/, // styled-components
|
|
45
|
+
// State classes that may change
|
|
46
|
+
/^(is-|has-|js-)/,
|
|
47
|
+
/^(active|selected|focused|disabled|hidden|visible)$/,
|
|
48
|
+
// Animation/transition classes
|
|
49
|
+
/^(fade|slide|animate)/,
|
|
50
|
+
/-(enter|leave|active)(-active|-done)?$/,
|
|
51
|
+
],
|
|
52
|
+
// Whitelist stable attribute selectors
|
|
53
|
+
whitelist: [
|
|
54
|
+
/^data-testid$/,
|
|
55
|
+
/^data-cy$/,
|
|
56
|
+
/^data-test$/,
|
|
57
|
+
/^data-qa$/,
|
|
58
|
+
/^aria-label$/,
|
|
59
|
+
/^role$/,
|
|
60
|
+
/^name$/,
|
|
61
|
+
/^type$/,
|
|
62
|
+
/^href$/,
|
|
63
|
+
],
|
|
64
|
+
});
|
|
65
|
+
return selector;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.warn('[SelectorGenerator] Failed to generate selector:', error);
|
|
69
|
+
// Fallback: try simpler approach
|
|
70
|
+
return generateFallbackSelector(element);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Fallback selector generation when the library fails.
|
|
75
|
+
* Creates a path-based selector from the element to the body.
|
|
76
|
+
*/
|
|
77
|
+
function generateFallbackSelector(element) {
|
|
78
|
+
const path = [];
|
|
79
|
+
let current = element;
|
|
80
|
+
while (current && current !== document.body && current !== document.documentElement) {
|
|
81
|
+
let selector = current.tagName.toLowerCase();
|
|
82
|
+
// Add ID if present
|
|
83
|
+
if (current.id) {
|
|
84
|
+
selector = `#${CSS.escape(current.id)}`;
|
|
85
|
+
path.unshift(selector);
|
|
86
|
+
break; // ID is unique enough
|
|
87
|
+
}
|
|
88
|
+
// Add nth-child for specificity
|
|
89
|
+
const parent = current.parentElement;
|
|
90
|
+
if (parent) {
|
|
91
|
+
const siblings = Array.from(parent.children);
|
|
92
|
+
const index = siblings.indexOf(current) + 1;
|
|
93
|
+
selector += `:nth-child(${index})`;
|
|
94
|
+
}
|
|
95
|
+
path.unshift(selector);
|
|
96
|
+
current = parent;
|
|
97
|
+
}
|
|
98
|
+
return path.join(' > ');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validates that a selector correctly targets the expected element.
|
|
102
|
+
*/
|
|
103
|
+
export function validateSelector(selector, expectedElement) {
|
|
104
|
+
try {
|
|
105
|
+
const matched = document.querySelector(selector);
|
|
106
|
+
return matched === expectedElement;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Gets a human-readable description of an element for UI display.
|
|
114
|
+
*/
|
|
115
|
+
export function getElementDescription(element) {
|
|
116
|
+
const tag = element.tagName.toLowerCase();
|
|
117
|
+
const id = element.id ? `#${element.id}` : '';
|
|
118
|
+
const classes = element.className && typeof element.className === 'string'
|
|
119
|
+
? `.${element.className
|
|
120
|
+
.split(' ')
|
|
121
|
+
.filter((c) => c && !isDynamicClass(c))
|
|
122
|
+
.slice(0, 2)
|
|
123
|
+
.join('.')}`
|
|
124
|
+
: '';
|
|
125
|
+
// Get text content preview
|
|
126
|
+
const text = element.textContent?.trim().slice(0, 30) || '';
|
|
127
|
+
const textPreview = text ? ` "${text}${text.length >= 30 ? '...' : ''}"` : '';
|
|
128
|
+
return `${tag}${id}${classes}${textPreview}`.trim();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Checks if a class name appears to be dynamically generated.
|
|
132
|
+
*/
|
|
133
|
+
function isDynamicClass(className) {
|
|
134
|
+
const dynamicPatterns = [
|
|
135
|
+
/^[a-z]+-[a-f0-9]{5,}$/i,
|
|
136
|
+
/^_[a-zA-Z0-9]+$/,
|
|
137
|
+
/^svelte-[a-z0-9]+$/i,
|
|
138
|
+
/^vue-[a-z0-9]+$/i,
|
|
139
|
+
/^emotion-[0-9]+$/,
|
|
140
|
+
/^sc-[a-zA-Z]+$/,
|
|
141
|
+
];
|
|
142
|
+
return dynamicPatterns.some((pattern) => pattern.test(className));
|
|
143
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@syntrologie/shared-editor-ui",
|
|
3
|
+
"version": "0.0.0-semantically-released",
|
|
4
|
+
"description": "Shared UI components for adaptive editor panels",
|
|
5
|
+
"license": "Proprietary",
|
|
6
|
+
"private": true,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./src/index.ts",
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./src/index.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"clean": "rm -rf dist",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"css-selector-generator": "^3.8.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": ">=18.0.0",
|
|
32
|
+
"react-dom": ">=18.0.0",
|
|
33
|
+
"lucide-react": ">=0.400.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@testing-library/dom": "^10.4.1",
|
|
37
|
+
"@testing-library/react": "^16.3.2",
|
|
38
|
+
"@types/react": "^19.2.0",
|
|
39
|
+
"jsdom": "^26.1.0",
|
|
40
|
+
"react": "^19.2.0",
|
|
41
|
+
"react-dom": "^19.2.0",
|
|
42
|
+
"typescript": "^5.9.3",
|
|
43
|
+
"vitest": "^4.0.18"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syntrologie/adapt-nav",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0-canary.2",
|
|
4
4
|
"description": "Adaptive Navigation - Nav link widget, scroll-to and page navigation actions",
|
|
5
5
|
"license": "Proprietary",
|
|
6
6
|
"private": false,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/SyntropyForge/amazing-demos.git",
|
|
11
|
-
"directory": "
|
|
11
|
+
"directory": "packages/adaptives/adaptive-nav"
|
|
12
12
|
},
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
@@ -31,7 +31,12 @@
|
|
|
31
31
|
"files": [
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
|
+
"bundledDependencies": [
|
|
35
|
+
"@syntro/design-system",
|
|
36
|
+
"@syntrologie/shared-editor-ui"
|
|
37
|
+
],
|
|
34
38
|
"scripts": {
|
|
39
|
+
"prepack": "node ../../../scripts/prepare-bundled-deps.mjs",
|
|
35
40
|
"build": "tsc",
|
|
36
41
|
"typecheck": "tsc --noEmit",
|
|
37
42
|
"clean": "rm -rf dist",
|
|
@@ -39,23 +44,23 @@
|
|
|
39
44
|
"test:watch": "vitest"
|
|
40
45
|
},
|
|
41
46
|
"peerDependencies": {
|
|
42
|
-
"@syntrologie/runtime-sdk": "^2.0.0",
|
|
43
47
|
"react": ">=18.0.0",
|
|
44
48
|
"react-dom": ">=18.0.0",
|
|
45
49
|
"zod": "^3.0.0"
|
|
46
50
|
},
|
|
47
51
|
"dependencies": {
|
|
48
52
|
"@syntrologie/shared-editor-ui": "*",
|
|
49
|
-
"@syntro/design-system": "
|
|
53
|
+
"@syntro/design-system": "*",
|
|
54
|
+
"@syntrologie/sdk-contracts": "*"
|
|
50
55
|
},
|
|
51
56
|
"devDependencies": {
|
|
52
|
-
"@types/react": "^19.
|
|
53
|
-
"typescript": "^5.
|
|
57
|
+
"@types/react": "^19.2.0",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
54
59
|
"zod": "^3.25.76",
|
|
55
60
|
"@testing-library/react": "^16.3.2",
|
|
56
|
-
"jsdom": "^
|
|
57
|
-
"react": "^19.2.
|
|
58
|
-
"react-dom": "^19.2.
|
|
59
|
-
"vitest": "^
|
|
61
|
+
"jsdom": "^26.1.0",
|
|
62
|
+
"react": "^19.2.0",
|
|
63
|
+
"react-dom": "^19.2.0",
|
|
64
|
+
"vitest": "^4.0.18"
|
|
60
65
|
}
|
|
61
66
|
}
|