@butternutbox/pawprint-native 0.10.9 → 0.10.11

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.
@@ -9,10 +9,10 @@
9
9
  DTS Build start
10
10
  CJS dist/index.cjs 1.80 MB
11
11
  CJS dist/index.cjs.map 2.70 MB
12
- CJS ⚡️ Build success in 11884ms
13
- ESM dist/index.js 1.72 MB
12
+ CJS ⚡️ Build success in 11449ms
13
+ ESM dist/index.js 1.73 MB
14
14
  ESM dist/index.js.map 2.70 MB
15
- ESM ⚡️ Build success in 11885ms
16
- DTS ⚡️ Build success in 22581ms
15
+ ESM ⚡️ Build success in 11453ms
16
+ DTS ⚡️ Build success in 22526ms
17
17
  DTS dist/index.d.cts 91.44 KB
18
18
  DTS dist/index.d.ts 91.44 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # @butternutbox/pawprint-native
2
2
 
3
+ ## 0.10.11
4
+
5
+ ### Patch Changes
6
+
7
+ - 27bbcb5: NumberField: center the label, small label and description/error copy over the
8
+ input on native.
9
+
10
+ Previously the label and help text were left-aligned across the full width of
11
+ the root, so they drifted away from the input group (which packs to the left
12
+ when not `fullWidth`). The copy now centers over the field: the root centers its
13
+ children when not `fullWidth`, and the label/help text use centered text so they
14
+ stay centered over the input in `fullWidth` mode too. Matches the Figma design.
15
+
16
+ ## 0.10.10
17
+
18
+ ### Patch Changes
19
+
20
+ - 8d9523c: Drawer: fix the body collapsing to zero height on native (regression in 0.10.9).
21
+
22
+ 0.10.9 made the panel wrap its content with no explicit height, relying on
23
+ `DrawerBody`'s `maxHeight` to size the `flex: 1` ScrollView. On native a
24
+ `ScrollView` has no intrinsic size and `flex: 1` (flexBasis 0) needs a
25
+ definite-height parent, so every drawer body collapsed to ~0 — only the header
26
+ and footer rendered. (It looked correct in the react-native-web Storybook, whose
27
+ flexbox sizes to content, which is why it slipped through.)
28
+
29
+ The panel now keeps an explicit height again (the pre-0.10.9 structure that
30
+ gives the ScrollView a bounded parent) AND re-fits it: `DrawerBody` reports its
31
+ natural scroll-content height via `onContentSizeChange` (measured in the
32
+ ScrollView's unbounded content container, so it's independent of the frame — no
33
+ feedback loop) through a new `DrawerMeasureContext`, and `DrawerContent` sizes
34
+ the panel to `chrome + min(content, windowHeight - 300)`, capped at 90% of the
35
+ window. `chrome` is locked once from the first, unbounded layout and is
36
+ invariant thereafter. Content that grows or shrinks after open (async load,
37
+ expanding sections) re-fits the panel; tall content caps and scrolls.
38
+
3
39
  ## 0.10.9
4
40
 
5
41
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -8877,6 +8877,8 @@ var DrawerOverlay = React65__default.default.forwardRef(({ accessible = false },
8877
8877
  DrawerOverlay.displayName = "Drawer.Overlay";
8878
8878
  var DrawerDragContext = React65__default.default.createContext(null);
8879
8879
  var useDrawerDragContext = () => React65__default.default.useContext(DrawerDragContext);
8880
+ var DrawerMeasureContext = React65.createContext(null);
8881
+ var useDrawerMeasureContext = () => React65.useContext(DrawerMeasureContext);
8880
8882
  var DrawerFooterContext = React65__default.default.createContext(false);
8881
8883
  var useDrawerFooterContext = () => React65__default.default.useContext(DrawerFooterContext);
8882
8884
  var DrawerHeaderContext = React65__default.default.createContext(null);
@@ -8895,17 +8897,12 @@ var StyledPanel2 = styled50__default.default(reactNative.View)(
8895
8897
  panelShadowColor,
8896
8898
  panelShadowOffsetY,
8897
8899
  panelShadowBlur,
8898
- panelMaxHeight
8899
- }) => ({
8900
+ panelFlex
8901
+ }) => __spreadProps(__spreadValues({
8900
8902
  width: "100%",
8901
8903
  maxWidth: panelMaxWidth,
8902
- // The panel wraps its content and caps at maxHeight. It is intentionally
8903
- // NOT given a fixed height: letting it size to content means it re-fits
8904
- // automatically whenever the body grows or shrinks (async load, expanding
8905
- // sections). The body's own maxHeight (see DrawerBody) bounds scrolling and
8906
- // keeps the ScrollView from collapsing, so no fixed panel height is needed.
8907
- maxHeight: panelMaxHeight,
8908
- alignSelf: "center",
8904
+ alignSelf: "center"
8905
+ }, panelFlex != null ? { flex: panelFlex } : void 0), {
8909
8906
  borderTopLeftRadius: panelBorderRadius,
8910
8907
  borderTopRightRadius: panelBorderRadius,
8911
8908
  borderTopWidth: panelBorderWidth,
@@ -8931,6 +8928,7 @@ var DrawerContent = React65__default.default.forwardRef(
8931
8928
  const { isOpen, closeDrawer, onExitComplete } = useDrawerContext();
8932
8929
  const { height: windowHeight } = reactNative.useWindowDimensions();
8933
8930
  const maxHeight = windowHeight * 0.9;
8931
+ const bodyMaxHeight = windowHeight - 300;
8934
8932
  const closeDrawerRef = React65.useRef(closeDrawer);
8935
8933
  React65.useEffect(() => {
8936
8934
  closeDrawerRef.current = closeDrawer;
@@ -8941,12 +8939,22 @@ var DrawerContent = React65__default.default.forwardRef(
8941
8939
  const entryRanRef = React65.useRef(false);
8942
8940
  const isOpenRef = React65.useRef(isOpen);
8943
8941
  const activeAnim = React65.useRef(null);
8942
+ const [panelHeight, setPanelHeight] = React65.useState(0);
8943
+ const chromeRef = React65.useRef(0);
8944
+ const bodyContentRef = React65.useRef(0);
8945
+ const firstNaturalRef = React65.useRef(0);
8944
8946
  React65.useEffect(() => {
8945
8947
  const id = translateY.addListener(({ value }) => {
8946
8948
  translateYValue.current = value;
8947
8949
  });
8948
8950
  return () => translateY.removeListener(id);
8949
8951
  }, [translateY]);
8952
+ React65.useEffect(() => {
8953
+ if (panelHeightRef.current > 0 && panelHeightRef.current > maxHeight) {
8954
+ setPanelHeight(maxHeight);
8955
+ panelHeightRef.current = maxHeight;
8956
+ }
8957
+ }, [maxHeight]);
8950
8958
  const runEntry = React65.useCallback(() => {
8951
8959
  var _a3;
8952
8960
  if (panelHeightRef.current === 0) return;
@@ -8993,17 +9001,59 @@ var DrawerContent = React65__default.default.forwardRef(
8993
9001
  runExit();
8994
9002
  }
8995
9003
  }, [isOpen, runEntry, runExit]);
9004
+ const applyRefit = React65.useCallback(() => {
9005
+ const chrome = chromeRef.current;
9006
+ const content = bodyContentRef.current;
9007
+ if (chrome <= 0 || content <= 0) return;
9008
+ const desired = Math.min(
9009
+ chrome + Math.min(content, bodyMaxHeight),
9010
+ maxHeight
9011
+ );
9012
+ if (Math.abs(desired - panelHeightRef.current) > 1) {
9013
+ panelHeightRef.current = desired;
9014
+ setPanelHeight(desired);
9015
+ }
9016
+ }, [bodyMaxHeight, maxHeight]);
9017
+ const lockChrome = React65.useCallback(() => {
9018
+ if (chromeRef.current > 0) return;
9019
+ const natural = firstNaturalRef.current;
9020
+ const content = bodyContentRef.current;
9021
+ if (natural <= 0 || content <= 0) return;
9022
+ chromeRef.current = natural - Math.min(content, bodyMaxHeight);
9023
+ }, [bodyMaxHeight]);
9024
+ const setBodyContentHeight = React65.useCallback(
9025
+ (height) => {
9026
+ if (height <= 0) return;
9027
+ bodyContentRef.current = height;
9028
+ lockChrome();
9029
+ applyRefit();
9030
+ },
9031
+ [lockChrome, applyRefit]
9032
+ );
9033
+ const measureContextValue = React65.useMemo(
9034
+ () => ({ setBodyContentHeight }),
9035
+ [setBodyContentHeight]
9036
+ );
8996
9037
  const onLayout = React65.useCallback(
8997
9038
  ({ nativeEvent }) => {
8998
9039
  const h = nativeEvent.layout.height;
8999
9040
  const capped = Math.min(h, maxHeight);
9000
9041
  if (capped <= 0) return;
9001
- panelHeightRef.current = capped;
9002
- if (isOpenRef.current && !entryRanRef.current) {
9042
+ if (entryRanRef.current) return;
9043
+ if (chromeRef.current <= 0) {
9044
+ firstNaturalRef.current = h;
9045
+ lockChrome();
9046
+ }
9047
+ if (capped !== panelHeightRef.current) {
9048
+ panelHeightRef.current = capped;
9049
+ setPanelHeight(capped);
9050
+ }
9051
+ if (isOpenRef.current) {
9003
9052
  runEntry();
9004
9053
  }
9054
+ applyRefit();
9005
9055
  },
9006
- [runEntry, maxHeight]
9056
+ [runEntry, maxHeight, lockChrome, applyRefit]
9007
9057
  );
9008
9058
  const panResponder = React65.useRef(
9009
9059
  reactNative.PanResponder.create({
@@ -9072,10 +9122,14 @@ var DrawerContent = React65__default.default.forwardRef(
9072
9122
  const headerContextValue = headerChild != null ? {
9073
9123
  variant: (_a2 = headerChild.props.variant) != null ? _a2 : "titleAndText"
9074
9124
  } : null;
9075
- return /* @__PURE__ */ jsxRuntime.jsx(DrawerHeaderContext.Provider, { value: headerContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerFooterContext.Provider, { value: hasFooter, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerDragContext.Provider, { value: dragContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
9125
+ return /* @__PURE__ */ jsxRuntime.jsx(DrawerHeaderContext.Provider, { value: headerContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerFooterContext.Provider, { value: hasFooter, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerMeasureContext.Provider, { value: measureContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerDragContext.Provider, { value: dragContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
9076
9126
  reactNative.Animated.View,
9077
9127
  {
9078
- style: [styles.animatedWrapper, { transform: [{ translateY }] }],
9128
+ style: [
9129
+ styles.animatedWrapper,
9130
+ panelHeight > 0 ? { height: panelHeight } : void 0,
9131
+ { transform: [{ translateY }] }
9132
+ ],
9079
9133
  children: /* @__PURE__ */ jsxRuntime.jsx(
9080
9134
  StyledPanel2,
9081
9135
  __spreadProps(__spreadValues({
@@ -9084,7 +9138,7 @@ var DrawerContent = React65__default.default.forwardRef(
9084
9138
  panelBorderRadius: parseTokenValue22(drawer.borderRadius.top),
9085
9139
  panelBgColor: colour.background.container.default,
9086
9140
  panelMaxWidth: parseTokenValue22(drawer.size.maxWidth),
9087
- panelMaxHeight: maxHeight,
9141
+ panelFlex: panelHeight > 0 ? 1 : void 0,
9088
9142
  panelBorderWidth: parseTokenValue22(dimensions3.borderWidth.sm),
9089
9143
  panelBorderColor: colour.border.default,
9090
9144
  panelShadowColor: modal.shadow.color,
@@ -9098,7 +9152,7 @@ var DrawerContent = React65__default.default.forwardRef(
9098
9152
  })
9099
9153
  )
9100
9154
  }
9101
- ) }) }) });
9155
+ ) }) }) }) });
9102
9156
  }
9103
9157
  );
9104
9158
  DrawerContent.displayName = "Drawer.Content";
@@ -9414,14 +9468,22 @@ var StyledScrollView = styled50__default.default(reactNative.ScrollView)(
9414
9468
  );
9415
9469
  var DrawerBody = React65__default.default.forwardRef(
9416
9470
  (_a, ref) => {
9417
- var _b = _a, { children, contentContainerStyle } = _b, props = __objRest(_b, ["children", "contentContainerStyle"]);
9471
+ var _b = _a, { children, contentContainerStyle, onContentSizeChange } = _b, props = __objRest(_b, ["children", "contentContainerStyle", "onContentSizeChange"]);
9418
9472
  const theme2 = react.useTheme();
9419
9473
  const { spacing } = theme2.tokens.components.drawer;
9420
9474
  const { buttons } = theme2.tokens.components;
9421
9475
  const { content } = spacing;
9422
9476
  const headerContext = useDrawerHeaderContext();
9423
9477
  const footerContext = useDrawerFooterContext();
9478
+ const measureContext = useDrawerMeasureContext();
9424
9479
  const { height: windowHeight } = reactNative.useWindowDimensions();
9480
+ const handleContentSizeChange = React65.useCallback(
9481
+ (width, height) => {
9482
+ measureContext == null ? void 0 : measureContext.setBodyContentHeight(height);
9483
+ onContentSizeChange == null ? void 0 : onContentSizeChange(width, height);
9484
+ },
9485
+ [measureContext, onContentSizeChange]
9486
+ );
9425
9487
  const gap = parseTokenValue26(content.slot.gap);
9426
9488
  const horizontalPadding = parseTokenValue26(content.slot.horizontalPadding);
9427
9489
  const topPadding = parseTokenValue26(content.slot.verticalPadding);
@@ -9437,6 +9499,7 @@ var DrawerBody = React65__default.default.forwardRef(
9437
9499
  bodyGap: gap,
9438
9500
  bodyMaxHeight,
9439
9501
  bodyPaddingBottom,
9502
+ onContentSizeChange: handleContentSizeChange,
9440
9503
  contentContainerStyle: [
9441
9504
  {
9442
9505
  gap,
@@ -10511,7 +10574,7 @@ NumberFieldInput.displayName = "NumberField.Input";
10511
10574
  var parseTokenValue35 = (value) => parseFloat(value);
10512
10575
  var StyledRoot10 = styled50__default.default(reactNative.View)(({ rootGap, fullWidth }) => __spreadValues({
10513
10576
  gap: rootGap
10514
- }, fullWidth && { width: "100%" }));
10577
+ }, fullWidth ? { width: "100%" } : { alignItems: "center" }));
10515
10578
  var StyledLabelGroup = styled50__default.default(reactNative.View)(({ labelGap }) => ({
10516
10579
  gap: labelGap
10517
10580
  }));
@@ -10575,6 +10638,7 @@ var NumberField = React65__default.default.forwardRef(
10575
10638
  {
10576
10639
  token: typoTokens.label,
10577
10640
  color: tokens3.colour.text.label,
10641
+ align: "center",
10578
10642
  children: label
10579
10643
  }
10580
10644
  ),
@@ -10583,6 +10647,7 @@ var NumberField = React65__default.default.forwardRef(
10583
10647
  {
10584
10648
  token: typoTokens.smallLabel,
10585
10649
  color: tokens3.colour.text.description,
10650
+ align: "center",
10586
10651
  children: smallLabel
10587
10652
  }
10588
10653
  )
@@ -10612,6 +10677,7 @@ var NumberField = React65__default.default.forwardRef(
10612
10677
  {
10613
10678
  token: size === "lg" ? tokens3.typography.large.secondaryContent : tokens3.typography.small.smallLabel,
10614
10679
  color: tokens3.colour.text.description,
10680
+ align: "center",
10615
10681
  children: description
10616
10682
  }
10617
10683
  ),
@@ -10620,6 +10686,7 @@ var NumberField = React65__default.default.forwardRef(
10620
10686
  {
10621
10687
  token: size === "lg" ? tokens3.typography.large.secondaryContent : tokens3.typography.small.smallLabel,
10622
10688
  color: theme2.tokens.components.inputs.colour.description.error,
10689
+ align: "center",
10623
10690
  children: error
10624
10691
  }
10625
10692
  )