@colixsystems/widget-sdk 0.266.0 → 0.266.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.
package/README.md CHANGED
@@ -86,7 +86,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
86
86
 
87
87
  ## Status
88
88
 
89
- `v0.266.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
89
+ `v0.266.1` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
90
+
91
+ ### What's new in 0.266.1 (contract 1.216.0)
92
+
93
+ **An open `<Modal>` or `<Overlay>` holds the page still on the web.** Scrolling past the end of a dialog's body, or over a dialog with nothing to scroll, used to scroll the page behind it. The page now stays put until the dialog closes, as it already did in the phone app. Nothing changes for a widget. An anchored `<Menu>`, `<Popover>` or `<Tooltip>` still closes when the page scrolls under it.
90
94
 
91
95
  ### What's new in 0.266.0 (contract 1.216.0)
92
96
 
@@ -82,6 +82,9 @@ const VALID_TYPES = new Set([
82
82
  "object", "array",
83
83
  ]);
84
84
 
85
+ /** The propertySchema field types, for documentation generated from this list. */
86
+ export const PROPERTY_TYPES = Object.freeze([...VALID_TYPES]);
87
+
85
88
  function isPlainObject(v) {
86
89
  return v !== null && typeof v === "object" && !Array.isArray(v);
87
90
  }
package/dist/web-modal.js CHANGED
@@ -59,6 +59,32 @@ function useCloseOnOutsideScroll(container, enabled, onCloseRef) {
59
59
  }, [container, enabled, onCloseRef]);
60
60
  }
61
61
 
62
+ // A dialog owns the screen, as on native: the page beneath must not
63
+ // scroll, even once the dialog's own body runs out of scroll.
64
+ let pageScrollLocks = 0;
65
+ let unlockedRootStyle = null;
66
+
67
+ function usePageScrollLock(enabled) {
68
+ React.useEffect(() => {
69
+ if (!enabled) return undefined;
70
+ const root = document.documentElement;
71
+ if (pageScrollLocks++ === 0) {
72
+ unlockedRootStyle = {
73
+ overflow: root.style.overflow,
74
+ scrollbarGutter: root.style.scrollbarGutter,
75
+ };
76
+ // Keep a visible scrollbar's space, so the page does not shift sideways.
77
+ if (window.innerWidth > root.clientWidth) root.style.scrollbarGutter = "stable";
78
+ root.style.overflow = "hidden";
79
+ }
80
+ return () => {
81
+ if (--pageScrollLocks > 0) return;
82
+ root.style.overflow = unlockedRootStyle.overflow;
83
+ root.style.scrollbarGutter = unlockedRootStyle.scrollbarGutter;
84
+ };
85
+ }, [enabled]);
86
+ }
87
+
62
88
  function tabStops(dialog) {
63
89
  return Array.from(dialog.querySelectorAll(FOCUSABLE)).filter(
64
90
  (node) => node.getAttribute("aria-hidden") !== "true",
@@ -147,6 +173,8 @@ function ModalLayer({
147
173
  }, [visible]);
148
174
  const container = useBodyContainer(visible);
149
175
  useCloseOnOutsideScroll(container, closesOnOutsideScroll, onCloseRef);
176
+ // An anchored panel closes on a scroll beneath instead.
177
+ usePageScrollLock(Boolean(container) && !closesOnOutsideScroll);
150
178
 
151
179
  React.useEffect(() => {
152
180
  const dialog = dialogRef.current;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colixsystems/widget-sdk",
3
- "version": "0.266.0",
3
+ "version": "0.266.1",
4
4
  "description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
5
5
  "homepage": "https://github.com/Colix-AB/AppStudio",
6
6
  "type": "module",