@select-org/select-post-builder 1.2.9 → 1.3.1

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.
@@ -20540,8 +20540,8 @@ const ANALYTICS_EVENTS = {
20540
20540
  },
20541
20541
  // Editor interaction
20542
20542
  EDITOR: {
20543
- FOCUSED: "post_builder_editor_focused",
20544
- TAB_SWITCHED: "post_builder_editor_tab_switched"
20543
+ FOCUSED: "post_builder_focused",
20544
+ TAB_SWITCHED: "post_builder_tab_switched"
20545
20545
  },
20546
20546
  // Feature discovery
20547
20547
  FEATURE: {
@@ -20578,11 +20578,6 @@ const ANALYTICS_EVENTS = {
20578
20578
  ATTEMPTED: "post_builder_publish_attempted",
20579
20579
  SUCCESS: "post_builder_publish_success",
20580
20580
  FAILED: "post_builder_publish_failed"
20581
- },
20582
- // NEW: Validation
20583
- VALIDATION: {
20584
- ERROR: "post_builder_validation_error"
20585
- // NEW
20586
20581
  }
20587
20582
  }, FEATURE_NAME_MAP = {
20588
20583
  // Tiptap Marks (inline formatting)
@@ -20618,8 +20613,7 @@ class SessionManager {
20618
20613
  placement: d,
20619
20614
  startTime: Date.now(),
20620
20615
  lastErrorType: null,
20621
- hasUserFocused: !1,
20622
- focusTime: null,
20616
+ focusSources: /* @__PURE__ */ new Set(),
20623
20617
  contentCreatedFired: !1,
20624
20618
  featureUsageCounts: /* @__PURE__ */ new Map()
20625
20619
  }), p;
@@ -20630,9 +20624,9 @@ class SessionManager {
20630
20624
  deleteSession(n) {
20631
20625
  this.sessions.delete(n);
20632
20626
  }
20633
- markFocused(n) {
20634
- const d = this.getSession(n);
20635
- d && !d.hasUserFocused && (d.hasUserFocused = !0, d.focusTime = Date.now());
20627
+ markFocused(n, d) {
20628
+ const p = this.getSession(n);
20629
+ return !p || p.focusSources.has(d) ? !1 : (p.focusSources.add(d), !0);
20636
20630
  }
20637
20631
  setLastError(n, d) {
20638
20632
  const p = this.getSession(n);
@@ -21812,16 +21806,18 @@ const analyticsStore = createStore((u, n) => ({
21812
21806
  debug: p.debug ?? !1
21813
21807
  }), p.debug;
21814
21808
  },
21815
- createSession: (d, p) => {
21809
+ createSession: (d, p = EditorPlacement.Feed) => {
21816
21810
  const { sessionManager: m, logEventFn: g, enabled: y, debug: b } = n(), S = m.createSession(d, p);
21817
21811
  if (y && g) {
21818
- const E = {
21819
- session_id: S,
21820
- timestamp: Date.now(),
21821
- editor_type: d,
21822
- editor_placement: p
21823
- // NEW
21824
- };
21812
+ const E = pickBy(
21813
+ {
21814
+ compose_session_id: S,
21815
+ timestamp: Date.now(),
21816
+ editor_type: d,
21817
+ editor_placement: p
21818
+ },
21819
+ (T) => T != null
21820
+ );
21825
21821
  g(ANALYTICS_EVENTS.SESSION.STARTED, E);
21826
21822
  }
21827
21823
  return S;
@@ -21839,7 +21835,7 @@ const analyticsStore = createStore((u, n) => ({
21839
21835
  if (!E)
21840
21836
  return;
21841
21837
  const T = {
21842
- session_id: d,
21838
+ compose_session_id: d,
21843
21839
  timestamp: Date.now(),
21844
21840
  editor_type: E.editorType,
21845
21841
  editor_placement: E.placement,
@@ -21907,17 +21903,20 @@ const analyticsStore = createStore((u, n) => ({
21907
21903
  }
21908
21904
  );
21909
21905
  },
21910
- trackEditorFocus: (d) => {
21911
- const { sessionManager: p, trackEvent: m } = n();
21912
- p.markFocused(d);
21913
- const g = p.getSession(d), y = g?.focusTime ? g.focusTime - g.startTime : null;
21914
- m(d, ANALYTICS_EVENTS.EDITOR.FOCUSED, {
21915
- time_to_focus_ms: y || void 0
21906
+ trackEditorFocus: (d, p) => {
21907
+ const { sessionManager: m, trackEvent: g } = n();
21908
+ if (!m.markFocused(d, p)) return;
21909
+ const y = m.getSession(d);
21910
+ g(d, ANALYTICS_EVENTS.EDITOR.FOCUSED, {
21911
+ surface: "editor",
21912
+ focus_source: p,
21913
+ time_to_focus_ms: y ? Date.now() - y.startTime : void 0
21916
21914
  });
21917
21915
  },
21918
21916
  trackTabSwitch: (d, p, m) => {
21919
21917
  const { trackEvent: g } = n();
21920
21918
  g(d, ANALYTICS_EVENTS.EDITOR.TAB_SWITCHED, {
21919
+ surface: "editor",
21921
21920
  from_tab: p,
21922
21921
  to_tab: m
21923
21922
  });
@@ -21990,14 +21989,6 @@ const analyticsStore = createStore((u, n) => ({
21990
21989
  option_count: p.option_count,
21991
21990
  option_type: p.option_type
21992
21991
  });
21993
- },
21994
- trackValidationError: (d, p) => {
21995
- const { trackEvent: m } = n();
21996
- m(d, ANALYTICS_EVENTS.VALIDATION.ERROR, {
21997
- field: p.field,
21998
- error_type: p.errorType,
21999
- error_message: p.errorMessage
22000
- });
22001
21992
  }
22002
21993
  }));
22003
21994
  function useAnalyticsStore(u) {
@@ -22012,7 +22003,7 @@ function useAnalyticsTracking() {
22012
22003
  trackPublish: (d) => n.trackPublish(u, d),
22013
22004
  trackAbandon: (d) => n.trackExplicitAbandon(u, d),
22014
22005
  trackFeature: (d) => n.trackFeature(u, d),
22015
- trackEditorFocus: () => n.trackEditorFocus(u),
22006
+ trackEditorFocus: (d) => n.trackEditorFocus(u, d),
22016
22007
  trackTabSwitch: (d, p) => n.trackTabSwitch(u, d, p),
22017
22008
  trackContentCreated: (d) => n.trackContentCreated(u, d),
22018
22009
  trackMediaUploadSuccess: (d) => n.trackMediaUploadSuccess(u, d),
@@ -22022,7 +22013,6 @@ function useAnalyticsTracking() {
22022
22013
  trackLinkUnfurlFailed: (d) => n.trackLinkUnfurlFailed(u, d),
22023
22014
  trackPollOptionAdded: (d) => n.trackPollOptionAdded(u, d),
22024
22015
  trackPollOptionRemoved: (d) => n.trackPollOptionRemoved(u, d),
22025
- trackValidationError: (d) => n.trackValidationError(u, d),
22026
22016
  // Direct access to sessionId if needed
22027
22017
  sessionId: u
22028
22018
  }),
@@ -39726,58 +39716,67 @@ const DialogClose = forwardRef((u, n) => /* @__PURE__ */ jsx(Close, { ref: n, "d
39726
39716
  }
39727
39717
  ));
39728
39718
  var PostBuilderEvents = /* @__PURE__ */ ((u) => (u.POST_PUBLISH_ATTEMPTED = "select:post_publish_attempted", u.POST_PUBLISH_SUCCESSFUL = "select:post_publish_success", u.POST_PUBLISH_FAILED = "select:post_publish_failed", u.POST_SESSION_ROTATED = "select:post_session_rotated", u.DRAFT_REHYDRATE_REQUEST = "select:draft_rehydrate_request", u))(PostBuilderEvents || {});
39719
+ const USER_INPUT_FOCUS_WINDOW_MS = 150;
39720
+ function classifyFocus(u, n) {
39721
+ return u !== null && n - u <= USER_INPUT_FOCUS_WINDOW_MS ? "user" : "auto";
39722
+ }
39729
39723
  function useEditorTracking({
39730
39724
  editor: u,
39731
39725
  editorType: n,
39732
39726
  idleTimeout: d = 3e5
39733
39727
  // 5 minutes default
39734
39728
  }) {
39735
- const { sessionId: p } = useAnalyticsSession(), m = useRef(), g = useRef(!1), y = useRef(!1), b = getAnalyticsStore(), S = useCallback(() => getEditorMetrics(u), [u]), E = useCallback(() => {
39736
- m.current && clearTimeout(m.current), !(!u || !p || y.current) && (m.current = setTimeout(() => {
39737
- const C = S();
39738
- C && !C.isEmpty && (b.trackExplicitAbandon(p, {
39739
- contentLength: C.characterCount,
39740
- hasUnsavedChanges: C.hasUnsavedChanges,
39729
+ const { sessionId: p } = useAnalyticsSession(), m = useRef(), g = useRef(!1), y = getAnalyticsStore(), b = useCallback(() => getEditorMetrics(u), [u]), S = useCallback(() => {
39730
+ m.current && clearTimeout(m.current), !(!u || !p || g.current) && (m.current = setTimeout(() => {
39731
+ const T = b();
39732
+ T && !T.isEmpty && (y.trackExplicitAbandon(p, {
39733
+ contentLength: T.characterCount,
39734
+ hasUnsavedChanges: T.hasUnsavedChanges,
39741
39735
  abandonReason: "idle_timeout"
39742
- }), y.current = !0);
39736
+ }), g.current = !0);
39743
39737
  }, d));
39744
- }, [u, p, d, b, S]), T = useCallback(() => {
39738
+ }, [u, p, d, y, b]), E = useCallback(() => {
39745
39739
  if (!u || !p) return;
39746
- const C = S();
39747
- C && (C.wordCount >= 1 || C.mediaCount > 0 || C.linkCount > 0 || C?.pollCount > 0) && b.trackContentCreated(p, {
39740
+ const T = b();
39741
+ T && (T.wordCount >= 1 || T.mediaCount > 0 || T.linkCount > 0 || T?.pollCount > 0) && y.trackContentCreated(p, {
39748
39742
  editorType: n,
39749
- wordCount: C.wordCount,
39750
- mediaCount: C.mediaCount,
39751
- linkCount: C.linkCount
39743
+ wordCount: T.wordCount,
39744
+ mediaCount: T.mediaCount,
39745
+ linkCount: T.linkCount
39752
39746
  });
39753
- }, [u, p, b, n, S]);
39747
+ }, [u, p, y, n, b]);
39754
39748
  useEffect(() => {
39755
39749
  if (!u || !p) return;
39756
- const C = () => {
39757
- g.current || (b.trackEditorFocus(p), g.current = !0, T()), E();
39758
- }, A = () => {
39759
- T(), E();
39750
+ let T = null;
39751
+ const C = (R) => {
39752
+ !(R.target instanceof Node) || !u.view.dom?.contains(R.target) || (T = performance.now(), y.trackEditorFocus(p, "user"));
39753
+ }, A = (R) => {
39754
+ R.key === "Tab" && (T = performance.now());
39755
+ }, k = () => {
39756
+ y.trackEditorFocus(p, classifyFocus(T, performance.now())), E(), S();
39757
+ }, _ = () => {
39758
+ E(), S();
39760
39759
  };
39761
- return u.on("focus", C), u.on("update", A), () => {
39762
- u.off("focus", C), u.off("update", A);
39760
+ return document.addEventListener("pointerdown", C, !0), document.addEventListener("keydown", A, !0), u.on("focus", k), u.on("update", _), () => {
39761
+ document.removeEventListener("pointerdown", C, !0), document.removeEventListener("keydown", A, !0), u.off("focus", k), u.off("update", _);
39763
39762
  };
39764
- }, [u, p, b, E, T]), useEffect(() => {
39763
+ }, [u, p, y, S, E]), useEffect(() => {
39765
39764
  if (!p) return;
39766
- const C = () => {
39767
- if (y.current) return;
39768
- const A = S();
39769
- A && !A.isEmpty && (b.trackExplicitAbandon(p, {
39770
- contentLength: A.characterCount,
39771
- hasUnsavedChanges: A.hasUnsavedChanges,
39765
+ const T = () => {
39766
+ if (g.current) return;
39767
+ const C = b();
39768
+ C && !C.isEmpty && (y.trackExplicitAbandon(p, {
39769
+ contentLength: C.characterCount,
39770
+ hasUnsavedChanges: C.hasUnsavedChanges,
39772
39771
  abandonReason: "navigation"
39773
- }), y.current = !0);
39772
+ }), g.current = !0);
39774
39773
  };
39775
- return window.addEventListener("beforeunload", C), () => {
39776
- window.removeEventListener("beforeunload", C), m.current && clearTimeout(m.current);
39774
+ return window.addEventListener("beforeunload", T), () => {
39775
+ window.removeEventListener("beforeunload", T), m.current && clearTimeout(m.current);
39777
39776
  };
39778
- }, [p, b, S]), useEffect(() => () => {
39779
- m.current && clearTimeout(m.current), b.deleteSession(p);
39780
- }, [b, p]);
39777
+ }, [p, y, b]), useEffect(() => () => {
39778
+ m.current && clearTimeout(m.current), y.deleteSession(p);
39779
+ }, [y, p]);
39781
39780
  }
39782
39781
  const useHostAnalyticsBridge = () => {
39783
39782
  const { sessionId: u, editorType: n, placement: d } = useAnalyticsSession(), p = useAnalyticsStore((b) => b.trackPublish), m = useAnalyticsStore((b) => b.deleteSession), g = useAnalyticsStore((b) => b.createSession), y = useRef(/* @__PURE__ */ new Set());
@@ -61085,7 +61084,7 @@ const PostBuilderEditor = ({
61085
61084
  const ye = (xe) => {
61086
61085
  if (!Z) return;
61087
61086
  const { newSessionId: me } = xe.detail;
61088
- te(me), Z.isFocused && se(me);
61087
+ te(me), Z.isFocused && se(me, "auto");
61089
61088
  };
61090
61089
  return window.addEventListener(
61091
61090
  PostBuilderEvents.POST_SESSION_ROTATED,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@select-org/select-post-builder",
3
- "version": "1.2.9",
3
+ "version": "1.3.1",
4
4
  "description": "A reusable, extensible Post Builder widget for the Select platform and beyond.",
5
5
  "main": "./dist/post-builder.cjs.js",
6
6
  "module": "./dist/post-builder.js",