@butternutbox/pawprint-native 0.22.0 → 0.23.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.
@@ -7,12 +7,12 @@
7
7
  CJS Build start
8
8
  ESM Build start
9
9
  DTS Build start
10
- ESM dist/index.js 518.12 KB
11
- ESM dist/index.js.map 1.06 MB
12
- ESM ⚡️ Build success in 7711ms
13
- CJS dist/index.cjs 548.33 KB
14
- CJS dist/index.cjs.map 1.06 MB
15
- CJS ⚡️ Build success in 7715ms
16
- DTS ⚡️ Build success in 22565ms
17
- DTS dist/index.d.cts 102.08 KB
18
- DTS dist/index.d.ts 102.08 KB
10
+ ESM dist/index.js 521.48 KB
11
+ ESM dist/index.js.map 1.07 MB
12
+ ESM ⚡️ Build success in 7569ms
13
+ CJS dist/index.cjs 551.88 KB
14
+ CJS dist/index.cjs.map 1.07 MB
15
+ CJS ⚡️ Build success in 7569ms
16
+ DTS ⚡️ Build success in 22834ms
17
+ DTS dist/index.d.cts 102.54 KB
18
+ DTS dist/index.d.ts 102.54 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @butternutbox/pawprint-native
2
2
 
3
+ ## 0.23.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 8506d1d: handle flex for when full width is false in buttons
8
+
9
+ ## 0.23.0
10
+
11
+ ### Minor Changes
12
+
13
+ - a970fa5: SelectField: add async search. Pass `onSearchQuery` alongside `searchable` to run a debounced query as the user types, with the returned items replacing the list. The component renders a loading spinner while the query runs, `errorText` if it rejects, and `noResultsText` if it resolves empty; any `children` act as the default list before the user types. New props: `onSearchQuery`, `debounceMs` (default 300), `errorText`. Exports a `SelectFieldSearchResult` type for the resolver's return shape.
14
+ - 1ba9b0f: update checkbox, badge and buttons to allow for multiple lines
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [1ba9b0f]
19
+ - @butternutbox/pawprint-tokens@0.5.0
20
+
3
21
  ## 0.22.0
4
22
 
5
23
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -1201,7 +1201,7 @@ var IconWrapper = styled51__default.default(reactNative.View)({
1201
1201
  });
1202
1202
  var StyledButton = styled51__default.default(reactNative.Pressable)(
1203
1203
  ({
1204
- buttonHeight,
1204
+ buttonMinHeight,
1205
1205
  buttonMinWidth,
1206
1206
  buttonPaddingHorizontal,
1207
1207
  buttonPaddingVertical,
@@ -1217,7 +1217,7 @@ var StyledButton = styled51__default.default(reactNative.Pressable)(
1217
1217
  alignItems: "center",
1218
1218
  justifyContent: "center",
1219
1219
  position: "relative",
1220
- height: buttonHeight,
1220
+ minHeight: buttonMinHeight,
1221
1221
  minWidth: buttonMinWidth,
1222
1222
  paddingHorizontal: buttonPaddingHorizontal,
1223
1223
  paddingVertical: buttonPaddingVertical,
@@ -1227,10 +1227,9 @@ var StyledButton = styled51__default.default(reactNative.Pressable)(
1227
1227
  opacity: buttonOpacity
1228
1228
  }, buttonBorderWidth ? { borderWidth: buttonBorderWidth, borderColor: buttonBorderColor } : {}), buttonFullWidth ? { width: "100%" } : {})
1229
1229
  );
1230
- var StyledTextWrapper = styled51__default.default(reactNative.View)(({ textOpacity }) => ({
1231
- opacity: textOpacity,
1232
- flexShrink: 0
1233
- }));
1230
+ var StyledTextWrapper = styled51__default.default(reactNative.View)(({ textOpacity, fullWidth }) => __spreadValues({
1231
+ opacity: textOpacity
1232
+ }, fullWidth ? { flex: 1 } : {}));
1234
1233
  var StyledSpinnerWrapper = styled51__default.default(reactNative.View)({
1235
1234
  position: "absolute",
1236
1235
  alignItems: "center",
@@ -1305,7 +1304,7 @@ var Button = React66__default.default.forwardRef(
1305
1304
  accessibilityState: { disabled: isDisabled, busy: loading },
1306
1305
  onPressIn: () => setPressed(true),
1307
1306
  onPressOut: () => setPressed(false),
1308
- buttonHeight: parseTokenValue7(sizeTokens.height),
1307
+ buttonMinHeight: parseTokenValue7(sizeTokens.minHeight),
1309
1308
  buttonMinWidth: parseTokenValue7(sizeTokens.minWidth),
1310
1309
  buttonPaddingHorizontal: parseTokenValue7(
1311
1310
  spacingTokens.horizontalPadding
@@ -1321,7 +1320,7 @@ var Button = React66__default.default.forwardRef(
1321
1320
  }, rest), {
1322
1321
  children: [
1323
1322
  startIcon && /* @__PURE__ */ jsxRuntime.jsx(IconWrapper, { children: startIcon }),
1324
- /* @__PURE__ */ jsxRuntime.jsx(StyledTextWrapper, { textOpacity: loading ? 0 : 1, children: /* @__PURE__ */ jsxRuntime.jsx(
1323
+ /* @__PURE__ */ jsxRuntime.jsx(StyledTextWrapper, { textOpacity: loading ? 0 : 1, fullWidth, children: /* @__PURE__ */ jsxRuntime.jsx(
1325
1324
  Typography,
1326
1325
  {
1327
1326
  token: {
@@ -1332,6 +1331,7 @@ var Button = React66__default.default.forwardRef(
1332
1331
  letterSpacing: typography.letterSpacing
1333
1332
  },
1334
1333
  color: variantStyles.textColor,
1334
+ align: "center",
1335
1335
  children
1336
1336
  }
1337
1337
  ) }),
@@ -1467,7 +1467,7 @@ var IconButton = React66__default.default.forwardRef(
1467
1467
  const isDisabled = disabled || loading;
1468
1468
  const buttons = theme2.tokens.components.buttons;
1469
1469
  const sizeTokens = buttons.size[size];
1470
- const dimension = parseTokenValue10(sizeTokens.height);
1470
+ const dimension = parseTokenValue10(sizeTokens.minHeight);
1471
1471
  const iconSizing = theme2.tokens.components.icons.sizing.icons.core;
1472
1472
  const iconDimension = parseTokenValue10(iconSizing[sizeToIconSizeToken[size]]);
1473
1473
  const [pressed, setPressed] = React66__default.default.useState(false);
@@ -4899,6 +4899,7 @@ Switch.displayName = "Switch";
4899
4899
  var parseTokenValue18 = (value) => parseFloat(value);
4900
4900
  var StyledTag = styled51__default.default(reactNative.View)(({ theme: theme2, tagVariant, tagSize }) => {
4901
4901
  const { sizing, spacing, colour, badge } = theme2.tokens.components.tags;
4902
+ const { spacing: semanticSpacing } = theme2.tokens.semantics.dimensions;
4902
4903
  const backgroundColorMap = {
4903
4904
  primary: colour.primary.background,
4904
4905
  secondary: colour.primary.secondary,
@@ -4908,13 +4909,21 @@ var StyledTag = styled51__default.default(reactNative.View)(({ theme: theme2, ta
4908
4909
  warning: colour.primary.warning,
4909
4910
  error: colour.primary.error
4910
4911
  };
4912
+ const verticalPaddingMap = {
4913
+ small: semanticSpacing["2xs"],
4914
+ medium: semanticSpacing["3xs"],
4915
+ large: semanticSpacing["2xs"]
4916
+ };
4911
4917
  return {
4912
4918
  flexDirection: "row",
4913
4919
  alignItems: "center",
4914
4920
  justifyContent: "center",
4915
- height: parseTokenValue18(sizing[tagSize].height),
4921
+ minHeight: parseTokenValue18(sizing[tagSize].minHeight),
4916
4922
  minWidth: parseTokenValue18(sizing[tagSize].minWidth),
4917
- paddingHorizontal: parseTokenValue18(spacing.horizontalPadding),
4923
+ paddingLeft: parseTokenValue18(spacing.horizontalPadding) * 2,
4924
+ paddingRight: parseTokenValue18(spacing.horizontalPadding) * 2,
4925
+ paddingTop: parseTokenValue18(verticalPaddingMap[tagSize]),
4926
+ paddingBottom: parseTokenValue18(verticalPaddingMap[tagSize]),
4918
4927
  gap: parseTokenValue18(spacing[tagSize].gap),
4919
4928
  borderRadius: parseTokenValue18(badge.borderRadius.default),
4920
4929
  backgroundColor: backgroundColorMap[tagVariant]
@@ -6363,7 +6372,7 @@ var DrawerBody = React66__default.default.forwardRef(
6363
6372
  const horizontalPadding = parseTokenValue27(content.slot.horizontalPadding);
6364
6373
  const topPadding = parseTokenValue27(content.slot.verticalPadding);
6365
6374
  const bodyMaxHeight = providedMaxHeight != null ? providedMaxHeight : windowHeight - 300;
6366
- const paddingRight = headerContext === null ? parseTokenValue27(spacing.close.right.md) + parseTokenValue27(buttons.size.sm.height) : horizontalPadding;
6375
+ const paddingRight = headerContext === null ? parseTokenValue27(spacing.close.right.md) + parseTokenValue27(buttons.size.sm.minHeight) : horizontalPadding;
6367
6376
  const bodyPaddingBottom = !footerContext ? Math.max(
6368
6377
  parseTokenValue27(theme2.tokens.semantics.dimensions.spacing["2xl"]),
6369
6378
  insets.bottom
@@ -6733,7 +6742,7 @@ var StyledRootPressable = styled51__default.default(reactNative.Pressable)(
6733
6742
  alignItems: rootFlexAlign,
6734
6743
  gap: rootGap,
6735
6744
  opacity: rootOpacity
6736
- }, rootPaddingVertical !== void 0 ? { paddingVertical: rootPaddingVertical } : {}), rootPaddingHorizontal !== void 0 ? { paddingHorizontal: rootPaddingHorizontal } : {}), rootMaxWidth !== void 0 ? rootFitContent ? { maxWidth: rootMaxWidth, alignSelf: "flex-start" } : { maxWidth: rootMaxWidth, width: "100%" } : { width: "100%" }), rootBgColor ? { backgroundColor: rootBgColor } : {}), rootBorderWidth !== void 0 ? { borderWidth: rootBorderWidth, borderColor: rootBorderColor } : {}), rootBorderRadius !== void 0 ? { borderRadius: rootBorderRadius } : {})
6745
+ }, rootPaddingVertical !== void 0 ? { paddingVertical: rootPaddingVertical } : {}), rootPaddingHorizontal !== void 0 ? { paddingHorizontal: rootPaddingHorizontal } : {}), rootMaxWidth !== void 0 ? rootFitContent ? { maxWidth: rootMaxWidth, alignSelf: "flex-start" } : { maxWidth: rootMaxWidth, width: "100%" } : {}), rootBgColor ? { backgroundColor: rootBgColor } : {}), rootBorderWidth !== void 0 ? { borderWidth: rootBorderWidth, borderColor: rootBorderColor } : {}), rootBorderRadius !== void 0 ? { borderRadius: rootBorderRadius } : {})
6737
6746
  );
6738
6747
  var StyledControl = styled51__default.default(reactNative.View)(
6739
6748
  ({
@@ -6754,12 +6763,12 @@ var StyledControl = styled51__default.default(reactNative.View)(
6754
6763
  justifyContent: "center"
6755
6764
  })
6756
6765
  );
6757
- var StyledContent2 = styled51__default.default(reactNative.View)(({ contentGap }) => ({
6766
+ var StyledContent2 = styled51__default.default(reactNative.View)(({ contentGap, contentFlex, contentFitContent }) => __spreadValues({
6758
6767
  flexDirection: "column",
6759
6768
  gap: contentGap,
6760
- flex: 1,
6769
+ flex: contentFlex,
6761
6770
  minWidth: 0
6762
- }));
6771
+ }, contentFitContent ? { maxWidth: "85%" } : {}));
6763
6772
  var StyledIllustration = styled51__default.default(reactNative.View)(({ illustrationSize }) => ({
6764
6773
  flexShrink: 0,
6765
6774
  width: illustrationSize,
@@ -6846,6 +6855,8 @@ var Checkbox = React66__default.default.forwardRef(
6846
6855
  StyledContent2,
6847
6856
  {
6848
6857
  contentGap: parseTokenValue31(checkbox.spacing.content.gap),
6858
+ contentFlex: isTile && fitContent ? 0 : 1,
6859
+ contentFitContent: isTile && fitContent,
6849
6860
  children: [
6850
6861
  label && /* @__PURE__ */ jsxRuntime.jsx(
6851
6862
  Typography,
@@ -9010,7 +9021,7 @@ var SelectFieldItem = React66__default.default.forwardRef(
9010
9021
  );
9011
9022
  SelectFieldItem.displayName = "SelectField.Item";
9012
9023
  var parseTokenValue48 = (value) => parseFloat(value);
9013
- var StyledNoResults = styled51__default.default(reactNative.View)(({ theme: theme2 }) => {
9024
+ var StyledStatusRow = styled51__default.default(reactNative.View)(({ theme: theme2 }) => {
9014
9025
  const { dropdown } = theme2.tokens.components.dropdownList;
9015
9026
  return {
9016
9027
  paddingVertical: parseTokenValue48(dropdown.listItem.spacing.verticalPadding),
@@ -9043,7 +9054,10 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9043
9054
  disabled,
9044
9055
  searchable = false,
9045
9056
  searchPlaceholder,
9046
- noResultsText = "No results found"
9057
+ noResultsText = "No results found",
9058
+ onSearchQuery,
9059
+ debounceMs = 300,
9060
+ errorText = "Something went wrong"
9047
9061
  } = _b, rest = __objRest(_b, [
9048
9062
  "label",
9049
9063
  "placeholder",
@@ -9059,7 +9073,10 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9059
9073
  "disabled",
9060
9074
  "searchable",
9061
9075
  "searchPlaceholder",
9062
- "noResultsText"
9076
+ "noResultsText",
9077
+ "onSearchQuery",
9078
+ "debounceMs",
9079
+ "errorText"
9063
9080
  ]);
9064
9081
  const [isOpen, setIsOpen] = React66__default.default.useState(false);
9065
9082
  const [showContent, setShowContent] = React66__default.default.useState(false);
@@ -9069,6 +9086,44 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9069
9086
  const [searchQuery, setSearchQuery] = React66__default.default.useState("");
9070
9087
  const [clearKey, setClearKey] = React66__default.default.useState(0);
9071
9088
  const searchInputRef = React66__default.default.useRef(null);
9089
+ const isQueryMode = searchable && typeof onSearchQuery === "function";
9090
+ const [searchResults, setSearchResults] = React66__default.default.useState([]);
9091
+ const [isSearching, setIsSearching] = React66__default.default.useState(false);
9092
+ const [searchFailed, setSearchFailed] = React66__default.default.useState(false);
9093
+ const searchRequestIdRef = React66__default.default.useRef(0);
9094
+ const onSearchQueryRef = React66__default.default.useRef(onSearchQuery);
9095
+ React66__default.default.useEffect(() => {
9096
+ onSearchQueryRef.current = onSearchQuery;
9097
+ });
9098
+ React66__default.default.useEffect(() => {
9099
+ if (!isQueryMode) return;
9100
+ if (searchQuery.length === 0) {
9101
+ searchRequestIdRef.current += 1;
9102
+ setSearchResults([]);
9103
+ setIsSearching(false);
9104
+ setSearchFailed(false);
9105
+ return;
9106
+ }
9107
+ const requestId = searchRequestIdRef.current + 1;
9108
+ searchRequestIdRef.current = requestId;
9109
+ setIsSearching(true);
9110
+ setSearchFailed(false);
9111
+ const debounceTimer = setTimeout(() => {
9112
+ const runQuery = onSearchQueryRef.current;
9113
+ if (!runQuery) return;
9114
+ Promise.resolve(runQuery(searchQuery)).then((items) => {
9115
+ if (searchRequestIdRef.current !== requestId) return;
9116
+ setSearchResults(items);
9117
+ setIsSearching(false);
9118
+ }).catch(() => {
9119
+ if (searchRequestIdRef.current !== requestId) return;
9120
+ setSearchResults([]);
9121
+ setSearchFailed(true);
9122
+ setIsSearching(false);
9123
+ });
9124
+ }, debounceMs);
9125
+ return () => clearTimeout(debounceTimer);
9126
+ }, [searchQuery, isQueryMode, debounceMs]);
9072
9127
  React66__default.default.useEffect(() => {
9073
9128
  if (!isOpen) {
9074
9129
  setShowContent(false);
@@ -9101,7 +9156,7 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9101
9156
  clearTimeout(hardwareKeyboardTimer);
9102
9157
  keyboardSub.remove();
9103
9158
  };
9104
- }, [isOpen, searchable]);
9159
+ }, [isOpen, searchable, isSearching, searchQuery]);
9105
9160
  const isCompound = React66__default.default.Children.toArray(children).some(
9106
9161
  (child) => React66__default.default.isValidElement(child) && child.type === SelectFieldContent
9107
9162
  );
@@ -9119,7 +9174,7 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9119
9174
  };
9120
9175
  const currentValue = value !== void 0 ? value : internalValue;
9121
9176
  const allItems = React66__default.default.Children.toArray(children);
9122
- const filteredItems = searchable ? allItems.filter((child) => {
9177
+ const localFilteredItems = searchable && !isQueryMode ? allItems.filter((child) => {
9123
9178
  var _a2;
9124
9179
  if (!searchQuery) return true;
9125
9180
  if (React66__default.default.isValidElement(child) && child.type === SelectFieldItem) {
@@ -9130,7 +9185,21 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9130
9185
  }
9131
9186
  return true;
9132
9187
  }) : allItems;
9133
- const hasNoResults = searchable && searchQuery.length > 0 && filteredItems.length === 0;
9188
+ const isQueryActive = isQueryMode && searchQuery.length > 0;
9189
+ const queryResultItems = searchResults.map((result) => /* @__PURE__ */ jsxRuntime.jsx(
9190
+ SelectFieldItem,
9191
+ {
9192
+ value: result.value,
9193
+ leadingIcon: result.leadingIcon,
9194
+ hintText: result.hintText,
9195
+ disabled: result.disabled,
9196
+ children: result.label
9197
+ },
9198
+ String(result.value)
9199
+ ));
9200
+ const itemsToRender = isQueryActive ? queryResultItems : localFilteredItems;
9201
+ const hasNoResults = isQueryMode ? isQueryActive && !isSearching && !searchFailed && searchResults.length === 0 : searchable && searchQuery.length > 0 && localFilteredItems.length === 0;
9202
+ const hasContentToShow = isSearching || searchFailed || hasNoResults || itemsToRender.length > 0;
9134
9203
  const searchActionIcon = (() => {
9135
9204
  if (!searchable) return void 0;
9136
9205
  const showClear = isOpen && searchQuery.length > 0 || !isOpen && Boolean(currentValue);
@@ -9189,8 +9258,8 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9189
9258
  description && /* @__PURE__ */ jsxRuntime.jsx(InputDescription, { state, children: description }),
9190
9259
  error && state === "error" && /* @__PURE__ */ jsxRuntime.jsx(InputError, { children: error })
9191
9260
  ] })),
9192
- showContent && /* @__PURE__ */ jsxRuntime.jsxs(SelectFieldContent, { children: [
9193
- filteredItems.map((child) => {
9261
+ showContent && hasContentToShow && /* @__PURE__ */ jsxRuntime.jsx(SelectFieldContent, { children: isSearching ? /* @__PURE__ */ jsxRuntime.jsx(StyledStatusRow, { children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm" }) }) : searchFailed ? /* @__PURE__ */ jsxRuntime.jsx(StyledStatusRow, { children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { size: "sm", children: errorText }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9262
+ itemsToRender.map((child) => {
9194
9263
  if (React66__default.default.isValidElement(child) && child.type === SelectFieldItem) {
9195
9264
  const selectedValue = currentValue && typeof currentValue === "object" && "value" in currentValue ? currentValue.value : currentValue;
9196
9265
  const childProps = child.props;
@@ -9203,8 +9272,8 @@ var SelectFieldRoot = React66__default.default.forwardRef(
9203
9272
  }
9204
9273
  return child;
9205
9274
  }),
9206
- hasNoResults && /* @__PURE__ */ jsxRuntime.jsx(StyledNoResults, { children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { size: "sm", children: noResultsText }) })
9207
- ] })
9275
+ hasNoResults && /* @__PURE__ */ jsxRuntime.jsx(StyledStatusRow, { children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { size: "sm", children: noResultsText }) })
9276
+ ] }) })
9208
9277
  ]
9209
9278
  },
9210
9279
  clearKey
@@ -9569,7 +9638,7 @@ var Slider = React66__default.default.forwardRef(
9569
9638
  const isControlled = controlledValue !== void 0;
9570
9639
  const [internalValue, setInternalValue] = React66__default.default.useState(defaultValue);
9571
9640
  const currentValue = isControlled ? controlledValue : internalValue;
9572
- const thumbSize = parseTokenValue49(buttons.size.md.height);
9641
+ const thumbSize = parseTokenValue49(buttons.size.md.minHeight);
9573
9642
  const trackHeight = parseTokenValue49(slider.sizing.track.height);
9574
9643
  const isWeb = reactNative.Platform.OS === "web";
9575
9644
  const [trackLayoutWidth, setTrackLayoutWidth] = React66.useState(0);