@inkindcards/semantic-layer 2.2.0 → 2.2.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.
@@ -61,8 +61,10 @@ interface InspectableProps {
61
61
  }
62
62
  /**
63
63
  * Wraps a data-bound component and registers it with the DataInspector overlay.
64
- * When no DataInspector/InspectableRegistry ancestor exists, renders as a plain div
65
- * with no overhead.
64
+ * Uses `display: contents` so the wrapper is invisible to CSS layout — charts,
65
+ * grids, and flex items render exactly as if Inspectable were not there.
66
+ * The inspect-mode highlight is rendered via a React portal into document.body,
67
+ * positioned with getBoundingClientRect().
66
68
  */
67
69
  declare function Inspectable({ label, currentSource, data, columns, children, }: InspectableProps): react_jsx_runtime.JSX.Element;
68
70
 
@@ -61,8 +61,10 @@ interface InspectableProps {
61
61
  }
62
62
  /**
63
63
  * Wraps a data-bound component and registers it with the DataInspector overlay.
64
- * When no DataInspector/InspectableRegistry ancestor exists, renders as a plain div
65
- * with no overhead.
64
+ * Uses `display: contents` so the wrapper is invisible to CSS layout — charts,
65
+ * grids, and flex items render exactly as if Inspectable were not there.
66
+ * The inspect-mode highlight is rendered via a React portal into document.body,
67
+ * positioned with getBoundingClientRect().
66
68
  */
67
69
  declare function Inspectable({ label, currentSource, data, columns, children, }: InspectableProps): react_jsx_runtime.JSX.Element;
68
70
 
@@ -1,6 +1,7 @@
1
1
  import { useMetrics, useAuth, useAdminFields, useAdminRoles, useAdminUsers } from './chunk-3OR3QCN6.js';
2
2
  import { createContext, useState, useMemo, useCallback, useContext, useId, useRef, useEffect } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { createPortal } from 'react-dom';
4
5
 
5
6
  var containerStyle = {
6
7
  fontFamily: "system-ui, -apple-system, sans-serif",
@@ -834,6 +835,21 @@ function InspectableRegistry({ children }) {
834
835
  };
835
836
  return /* @__PURE__ */ jsx(InspectableRegistryContext.Provider, { value, children });
836
837
  }
838
+ function getChildrenBounds(el) {
839
+ const children = el.children;
840
+ if (children.length === 0) return null;
841
+ let top = Infinity, left = Infinity, bottom = -Infinity, right = -Infinity;
842
+ for (let i = 0; i < children.length; i++) {
843
+ const r = children[i].getBoundingClientRect();
844
+ if (r.width === 0 && r.height === 0) continue;
845
+ top = Math.min(top, r.top);
846
+ left = Math.min(left, r.left);
847
+ bottom = Math.max(bottom, r.bottom);
848
+ right = Math.max(right, r.right);
849
+ }
850
+ if (top === Infinity) return null;
851
+ return new DOMRect(left, top, right - left, bottom - top);
852
+ }
837
853
  function Inspectable({
838
854
  label,
839
855
  currentSource = "unknown",
@@ -843,7 +859,8 @@ function Inspectable({
843
859
  }) {
844
860
  const registry = useContext(InspectableRegistryContext);
845
861
  const id = useId();
846
- const ref = useRef(null);
862
+ const wrapperRef = useRef(null);
863
+ const [rect, setRect] = useState(null);
847
864
  const inferredColumns = columns ?? (data?.[0] ? Object.keys(data[0]) : []);
848
865
  const sampleValues = data?.slice(0, 3) ?? [];
849
866
  useEffect(() => {
@@ -854,59 +871,86 @@ function Inspectable({
854
871
  currentSource,
855
872
  columns: inferredColumns,
856
873
  sampleValues,
857
- element: ref.current
874
+ element: wrapperRef.current
858
875
  });
859
876
  return () => registry.unregister(id);
860
877
  }, [id, label, currentSource, inferredColumns.join(","), registry]);
878
+ useEffect(() => {
879
+ if (!registry?.inspectActive || !wrapperRef.current) {
880
+ setRect(null);
881
+ return;
882
+ }
883
+ const measure = () => {
884
+ if (wrapperRef.current) {
885
+ setRect(getChildrenBounds(wrapperRef.current));
886
+ }
887
+ };
888
+ measure();
889
+ window.addEventListener("scroll", measure, true);
890
+ window.addEventListener("resize", measure);
891
+ const interval = setInterval(measure, 300);
892
+ return () => {
893
+ window.removeEventListener("scroll", measure, true);
894
+ window.removeEventListener("resize", measure);
895
+ clearInterval(interval);
896
+ };
897
+ }, [registry?.inspectActive]);
861
898
  if (!registry) {
862
899
  return /* @__PURE__ */ jsx(Fragment, { children });
863
900
  }
864
901
  const isSelected = registry.selectedId === id;
865
- const showOutline = registry.inspectActive;
866
902
  const handleClick = (e) => {
867
- if (!registry.inspectActive) return;
868
903
  e.stopPropagation();
904
+ e.preventDefault();
869
905
  registry.setSelectedId(isSelected ? null : id);
870
906
  };
871
- return /* @__PURE__ */ jsxs(
872
- "div",
873
- {
874
- ref,
875
- onClick: handleClick,
876
- style: {
877
- position: "relative",
878
- outline: showOutline ? isSelected ? "2px solid #3b82f6" : "2px dashed #93c5fd" : "none",
879
- outlineOffset: 2,
880
- borderRadius: 4,
881
- cursor: showOutline ? "pointer" : "inherit",
882
- transition: "outline 0.15s ease"
883
- },
884
- children: [
885
- showOutline && /* @__PURE__ */ jsx(
886
- "div",
887
- {
888
- style: {
889
- position: "absolute",
890
- top: -10,
891
- left: 4,
892
- fontSize: 10,
893
- fontWeight: 600,
894
- fontFamily: "system-ui, -apple-system, sans-serif",
895
- color: "#fff",
896
- backgroundColor: isSelected ? "#3b82f6" : "#93c5fd",
897
- padding: "1px 6px",
898
- borderRadius: 3,
899
- zIndex: 1e4,
900
- pointerEvents: "none",
901
- whiteSpace: "nowrap"
902
- },
903
- children: label
904
- }
905
- ),
906
- children
907
- ]
908
- }
909
- );
907
+ return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, style: { display: "contents" }, children: [
908
+ children,
909
+ registry.inspectActive && rect && createPortal(
910
+ /* @__PURE__ */ jsx(
911
+ "div",
912
+ {
913
+ onClick: handleClick,
914
+ style: {
915
+ position: "fixed",
916
+ top: rect.top,
917
+ left: rect.left,
918
+ width: rect.width,
919
+ height: rect.height,
920
+ zIndex: 9999,
921
+ cursor: "pointer",
922
+ outline: isSelected ? "2px solid #3b82f6" : "2px dashed #93c5fd",
923
+ outlineOffset: 2,
924
+ borderRadius: 4,
925
+ transition: "outline 0.15s ease",
926
+ background: isSelected ? "rgba(59,130,246,0.05)" : "transparent",
927
+ pointerEvents: "auto"
928
+ },
929
+ children: /* @__PURE__ */ jsx(
930
+ "div",
931
+ {
932
+ style: {
933
+ position: "absolute",
934
+ top: -10,
935
+ left: 4,
936
+ fontSize: 10,
937
+ fontWeight: 600,
938
+ fontFamily: "system-ui, -apple-system, sans-serif",
939
+ color: "#fff",
940
+ backgroundColor: isSelected ? "#3b82f6" : "#93c5fd",
941
+ padding: "1px 6px",
942
+ borderRadius: 3,
943
+ pointerEvents: "none",
944
+ whiteSpace: "nowrap"
945
+ },
946
+ children: label
947
+ }
948
+ )
949
+ }
950
+ ),
951
+ document.body
952
+ )
953
+ ] });
910
954
  }
911
955
 
912
956
  // src/components/field-matcher.ts