hs-uix 1.6.3 → 1.6.4

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/dist/datatable.js CHANGED
@@ -186,6 +186,8 @@ var DataTable = ({
186
186
  showFirstLastButtons,
187
187
  // show First/Last page buttons (default: auto when pageCount > 5)
188
188
  // Row count
189
+ title,
190
+ // optional title shown above the table toolbar
189
191
  showRowCount = true,
190
192
  // show "X records" / "X of Y records" text
191
193
  rowCountBold = false,
@@ -655,6 +657,9 @@ var DataTable = ({
655
657
  selectionResetRef.current = combinedSelectionResetKey;
656
658
  }, [combinedSelectionResetKey, selectable, externalSelectedIds]);
657
659
  const selectedIds = externalSelectedIds != null ? new Set(externalSelectedIds) : internalSelectedIds;
660
+ const showToolbarCount = showRowCount && !title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
661
+ const showTitleCount = showRowCount && !!title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
662
+ const hasToolbarContent = showSearch && searchFields.length > 0 || filters.length > 0 || activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) || showToolbarCount;
658
663
  const showRowActionsColumn = !!rowActions && !(hideRowActionsWhenSelectionActive && selectable && selectedIds.size > 0);
659
664
  const applySelection = (0, import_react.useCallback)((nextSet) => {
660
665
  if (externalSelectedIds == null) {
@@ -1004,7 +1009,7 @@ var DataTable = ({
1004
1009
  }
1005
1010
  );
1006
1011
  };
1007
- return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ import_react.default.createElement(
1012
+ return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, title && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", justify: "between", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Heading, null, title), showTitleCount && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)), hasToolbarContent && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ import_react.default.createElement(
1008
1013
  import_ui_extensions.SearchInput,
1009
1014
  {
1010
1015
  name: "datatable-search",
@@ -1030,7 +1035,7 @@ var DataTable = ({
1030
1035
  onClick: () => handleFilterRemove("all")
1031
1036
  },
1032
1037
  resolvedClearAllLabel
1033
- )))), showRowCount && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0) && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1038
+ )))), showToolbarCount && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1034
1039
  selectedIds,
1035
1040
  selectedCount: selectedIds.size,
1036
1041
  displayCount,
@@ -10,6 +10,7 @@ import {
10
10
  EmptyState,
11
11
  ErrorState,
12
12
  Flex,
13
+ Heading,
13
14
  Icon,
14
15
  Input,
15
16
  Link,
@@ -182,6 +183,8 @@ var DataTable = ({
182
183
  showFirstLastButtons,
183
184
  // show First/Last page buttons (default: auto when pageCount > 5)
184
185
  // Row count
186
+ title,
187
+ // optional title shown above the table toolbar
185
188
  showRowCount = true,
186
189
  // show "X records" / "X of Y records" text
187
190
  rowCountBold = false,
@@ -651,6 +654,9 @@ var DataTable = ({
651
654
  selectionResetRef.current = combinedSelectionResetKey;
652
655
  }, [combinedSelectionResetKey, selectable, externalSelectedIds]);
653
656
  const selectedIds = externalSelectedIds != null ? new Set(externalSelectedIds) : internalSelectedIds;
657
+ const showToolbarCount = showRowCount && !title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
658
+ const showTitleCount = showRowCount && !!title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
659
+ const hasToolbarContent = showSearch && searchFields.length > 0 || filters.length > 0 || activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) || showToolbarCount;
654
660
  const showRowActionsColumn = !!rowActions && !(hideRowActionsWhenSelectionActive && selectable && selectedIds.size > 0);
655
661
  const applySelection = useCallback((nextSet) => {
656
662
  if (externalSelectedIds == null) {
@@ -1000,7 +1006,7 @@ var DataTable = ({
1000
1006
  }
1001
1007
  );
1002
1008
  };
1003
- return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ React.createElement(Box, { flex: 3 }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ React.createElement(
1009
+ return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, title && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", justify: "between", gap: "sm" }, /* @__PURE__ */ React.createElement(Heading, null, title), showTitleCount && /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)), hasToolbarContent && /* @__PURE__ */ React.createElement(Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ React.createElement(Box, { flex: 3 }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ React.createElement(
1004
1010
  SearchInput,
1005
1011
  {
1006
1012
  name: "datatable-search",
@@ -1026,7 +1032,7 @@ var DataTable = ({
1026
1032
  onClick: () => handleFilterRemove("all")
1027
1033
  },
1028
1034
  resolvedClearAllLabel
1029
- )))), showRowCount && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0) && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1035
+ )))), showToolbarCount && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1030
1036
  selectedIds,
1031
1037
  selectedCount: selectedIds.size,
1032
1038
  displayCount,
package/dist/form.js CHANGED
@@ -404,6 +404,8 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
404
404
  // () => void
405
405
  submitPosition = "bottom",
406
406
  // "bottom" | "none"
407
+ submitAlign,
408
+ // default single-step action row alignment
407
409
  loading: controlledLoading,
408
410
  // controlled loading state
409
411
  disabled = false,
@@ -708,6 +710,10 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
708
710
  console.warn(`[FormBuilder] ${message}`);
709
711
  }
710
712
  }, [isDev]);
713
+ (0, import_react.useEffect)(() => {
714
+ if (!isMultiStep || !submitAlign) return;
715
+ warnConfig("submitAlign is ignored when steps are provided. Use renderButtons for custom multi-step button layout.");
716
+ }, [isMultiStep, submitAlign, warnConfig]);
711
717
  const replaceErrors = (0, import_react.useCallback)(
712
718
  (nextErrors) => {
713
719
  if (controlledErrors == null) setInternalErrors(nextErrors);
@@ -2310,6 +2316,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
2310
2316
  if (submitPosition === "none" || formReadOnly) return null;
2311
2317
  const isLastStep = !isMultiStep || currentStep === steps.length - 1;
2312
2318
  const isFirstStep = !isMultiStep || currentStep === 0;
2319
+ const singleStepJustify = submitAlign || (showCancel ? "between" : "start");
2313
2320
  const buttonContext = {
2314
2321
  isMultiStep,
2315
2322
  isFirstStep,
@@ -2344,7 +2351,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
2344
2351
  submitButtonLabel
2345
2352
  ) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "primary", onClick: handleNext, disabled }, nextButtonLabel)));
2346
2353
  }
2347
- return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: showCancel ? "between" : "start", gap: "sm" }, showCancel && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ import_react.default.createElement(
2354
+ return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: singleStepJustify, gap: "sm" }, showCancel && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Button, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ import_react.default.createElement(
2348
2355
  import_ui_extensions.LoadingButton,
2349
2356
  {
2350
2357
  variant: submitVariant,
package/dist/form.mjs CHANGED
@@ -408,6 +408,8 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
408
408
  // () => void
409
409
  submitPosition = "bottom",
410
410
  // "bottom" | "none"
411
+ submitAlign,
412
+ // default single-step action row alignment
411
413
  loading: controlledLoading,
412
414
  // controlled loading state
413
415
  disabled = false,
@@ -712,6 +714,10 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
712
714
  console.warn(`[FormBuilder] ${message}`);
713
715
  }
714
716
  }, [isDev]);
717
+ useEffect(() => {
718
+ if (!isMultiStep || !submitAlign) return;
719
+ warnConfig("submitAlign is ignored when steps are provided. Use renderButtons for custom multi-step button layout.");
720
+ }, [isMultiStep, submitAlign, warnConfig]);
715
721
  const replaceErrors = useCallback(
716
722
  (nextErrors) => {
717
723
  if (controlledErrors == null) setInternalErrors(nextErrors);
@@ -2314,6 +2320,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
2314
2320
  if (submitPosition === "none" || formReadOnly) return null;
2315
2321
  const isLastStep = !isMultiStep || currentStep === steps.length - 1;
2316
2322
  const isFirstStep = !isMultiStep || currentStep === 0;
2323
+ const singleStepJustify = submitAlign || (showCancel ? "between" : "start");
2317
2324
  const buttonContext = {
2318
2325
  isMultiStep,
2319
2326
  isFirstStep,
@@ -2348,7 +2355,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
2348
2355
  submitButtonLabel
2349
2356
  ) : /* @__PURE__ */ React.createElement(Button, { variant: "primary", onClick: handleNext, disabled }, nextButtonLabel)));
2350
2357
  }
2351
- return /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: showCancel ? "between" : "start", gap: "sm" }, showCancel && /* @__PURE__ */ React.createElement(Button, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ React.createElement(
2358
+ return /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: singleStepJustify, gap: "sm" }, showCancel && /* @__PURE__ */ React.createElement(Button, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ React.createElement(
2352
2359
  LoadingButton,
2353
2360
  {
2354
2361
  variant: submitVariant,
package/dist/index.js CHANGED
@@ -217,6 +217,8 @@ var DataTable = ({
217
217
  showFirstLastButtons,
218
218
  // show First/Last page buttons (default: auto when pageCount > 5)
219
219
  // Row count
220
+ title,
221
+ // optional title shown above the table toolbar
220
222
  showRowCount = true,
221
223
  // show "X records" / "X of Y records" text
222
224
  rowCountBold = false,
@@ -686,6 +688,9 @@ var DataTable = ({
686
688
  selectionResetRef.current = combinedSelectionResetKey;
687
689
  }, [combinedSelectionResetKey, selectable, externalSelectedIds]);
688
690
  const selectedIds = externalSelectedIds != null ? new Set(externalSelectedIds) : internalSelectedIds;
691
+ const showToolbarCount = showRowCount && !title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
692
+ const showTitleCount = showRowCount && !!title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
693
+ const hasToolbarContent = showSearch && searchFields.length > 0 || filters.length > 0 || activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) || showToolbarCount;
689
694
  const showRowActionsColumn = !!rowActions && !(hideRowActionsWhenSelectionActive && selectable && selectedIds.size > 0);
690
695
  const applySelection = (0, import_react.useCallback)((nextSet) => {
691
696
  if (externalSelectedIds == null) {
@@ -1035,7 +1040,7 @@ var DataTable = ({
1035
1040
  }
1036
1041
  );
1037
1042
  };
1038
- return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ import_react.default.createElement(
1043
+ return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, title && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", justify: "between", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Heading, null, title), showTitleCount && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)), hasToolbarContent && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ import_react.default.createElement(
1039
1044
  import_ui_extensions.SearchInput,
1040
1045
  {
1041
1046
  name: "datatable-search",
@@ -1061,7 +1066,7 @@ var DataTable = ({
1061
1066
  onClick: () => handleFilterRemove("all")
1062
1067
  },
1063
1068
  resolvedClearAllLabel
1064
- )))), showRowCount && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0) && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1069
+ )))), showToolbarCount && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1065
1070
  selectedIds,
1066
1071
  selectedCount: selectedIds.size,
1067
1072
  displayCount,
@@ -1540,6 +1545,8 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
1540
1545
  // () => void
1541
1546
  submitPosition = "bottom",
1542
1547
  // "bottom" | "none"
1548
+ submitAlign,
1549
+ // default single-step action row alignment
1543
1550
  loading: controlledLoading,
1544
1551
  // controlled loading state
1545
1552
  disabled = false,
@@ -1844,6 +1851,10 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
1844
1851
  console.warn(`[FormBuilder] ${message}`);
1845
1852
  }
1846
1853
  }, [isDev]);
1854
+ (0, import_react2.useEffect)(() => {
1855
+ if (!isMultiStep || !submitAlign) return;
1856
+ warnConfig("submitAlign is ignored when steps are provided. Use renderButtons for custom multi-step button layout.");
1857
+ }, [isMultiStep, submitAlign, warnConfig]);
1847
1858
  const replaceErrors = (0, import_react2.useCallback)(
1848
1859
  (nextErrors) => {
1849
1860
  if (controlledErrors == null) setInternalErrors(nextErrors);
@@ -3446,6 +3457,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
3446
3457
  if (submitPosition === "none" || formReadOnly) return null;
3447
3458
  const isLastStep = !isMultiStep || currentStep === steps.length - 1;
3448
3459
  const isFirstStep = !isMultiStep || currentStep === 0;
3460
+ const singleStepJustify = submitAlign || (showCancel ? "between" : "start");
3449
3461
  const buttonContext = {
3450
3462
  isMultiStep,
3451
3463
  isFirstStep,
@@ -3480,7 +3492,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
3480
3492
  submitButtonLabel
3481
3493
  ) : /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Button, { variant: "primary", onClick: handleNext, disabled }, nextButtonLabel)));
3482
3494
  }
3483
- return /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Flex, { direction: "row", justify: showCancel ? "between" : "start", gap: "sm" }, showCancel && /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Button, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ import_react2.default.createElement(
3495
+ return /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Flex, { direction: "row", justify: singleStepJustify, gap: "sm" }, showCancel && /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Button, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ import_react2.default.createElement(
3484
3496
  import_ui_extensions2.LoadingButton,
3485
3497
  {
3486
3498
  variant: submitVariant,
package/dist/index.mjs CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  EmptyState,
11
11
  ErrorState,
12
12
  Flex,
13
+ Heading,
13
14
  Icon,
14
15
  Input,
15
16
  Link,
@@ -182,6 +183,8 @@ var DataTable = ({
182
183
  showFirstLastButtons,
183
184
  // show First/Last page buttons (default: auto when pageCount > 5)
184
185
  // Row count
186
+ title,
187
+ // optional title shown above the table toolbar
185
188
  showRowCount = true,
186
189
  // show "X records" / "X of Y records" text
187
190
  rowCountBold = false,
@@ -651,6 +654,9 @@ var DataTable = ({
651
654
  selectionResetRef.current = combinedSelectionResetKey;
652
655
  }, [combinedSelectionResetKey, selectable, externalSelectedIds]);
653
656
  const selectedIds = externalSelectedIds != null ? new Set(externalSelectedIds) : internalSelectedIds;
657
+ const showToolbarCount = showRowCount && !title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
658
+ const showTitleCount = showRowCount && !!title && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0);
659
+ const hasToolbarContent = showSearch && searchFields.length > 0 || filters.length > 0 || activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) || showToolbarCount;
654
660
  const showRowActionsColumn = !!rowActions && !(hideRowActionsWhenSelectionActive && selectable && selectedIds.size > 0);
655
661
  const applySelection = useCallback((nextSet) => {
656
662
  if (externalSelectedIds == null) {
@@ -1000,7 +1006,7 @@ var DataTable = ({
1000
1006
  }
1001
1007
  );
1002
1008
  };
1003
- return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ React.createElement(Box, { flex: 3 }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ React.createElement(
1009
+ return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, title && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", justify: "between", gap: "sm" }, /* @__PURE__ */ React.createElement(Heading, null, title), showTitleCount && /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)), hasToolbarContent && /* @__PURE__ */ React.createElement(Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ React.createElement(Box, { flex: 3 }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ React.createElement(
1004
1010
  SearchInput,
1005
1011
  {
1006
1012
  name: "datatable-search",
@@ -1026,7 +1032,7 @@ var DataTable = ({
1026
1032
  onClick: () => handleFilterRemove("all")
1027
1033
  },
1028
1034
  resolvedClearAllLabel
1029
- )))), showRowCount && displayCount > 0 && !(showSelectionBar && selectable && selectedIds.size > 0) && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1035
+ )))), showToolbarCount && /* @__PURE__ */ React.createElement(Box, { flex: 1, alignSelf: "end" }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", justify: "end" }, /* @__PURE__ */ React.createElement(Text, { variant: "microcopy", format: rowCountBold ? { fontWeight: "bold" } : void 0 }, recordCountLabel)))), showSelectionBar && selectable && selectedIds.size > 0 && (renderSelectionBar ? renderSelectionBar({
1030
1036
  selectedIds,
1031
1037
  selectedCount: selectedIds.size,
1032
1038
  displayCount,
@@ -1545,6 +1551,8 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
1545
1551
  // () => void
1546
1552
  submitPosition = "bottom",
1547
1553
  // "bottom" | "none"
1554
+ submitAlign,
1555
+ // default single-step action row alignment
1548
1556
  loading: controlledLoading,
1549
1557
  // controlled loading state
1550
1558
  disabled = false,
@@ -1849,6 +1857,10 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
1849
1857
  console.warn(`[FormBuilder] ${message}`);
1850
1858
  }
1851
1859
  }, [isDev]);
1860
+ useEffect2(() => {
1861
+ if (!isMultiStep || !submitAlign) return;
1862
+ warnConfig("submitAlign is ignored when steps are provided. Use renderButtons for custom multi-step button layout.");
1863
+ }, [isMultiStep, submitAlign, warnConfig]);
1852
1864
  const replaceErrors = useCallback2(
1853
1865
  (nextErrors) => {
1854
1866
  if (controlledErrors == null) setInternalErrors(nextErrors);
@@ -3451,6 +3463,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
3451
3463
  if (submitPosition === "none" || formReadOnly) return null;
3452
3464
  const isLastStep = !isMultiStep || currentStep === steps.length - 1;
3453
3465
  const isFirstStep = !isMultiStep || currentStep === 0;
3466
+ const singleStepJustify = submitAlign || (showCancel ? "between" : "start");
3454
3467
  const buttonContext = {
3455
3468
  isMultiStep,
3456
3469
  isFirstStep,
@@ -3485,7 +3498,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
3485
3498
  submitButtonLabel
3486
3499
  ) : /* @__PURE__ */ React2.createElement(Button2, { variant: "primary", onClick: handleNext, disabled }, nextButtonLabel)));
3487
3500
  }
3488
- return /* @__PURE__ */ React2.createElement(Flex2, { direction: "row", justify: showCancel ? "between" : "start", gap: "sm" }, showCancel && /* @__PURE__ */ React2.createElement(Button2, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ React2.createElement(
3501
+ return /* @__PURE__ */ React2.createElement(Flex2, { direction: "row", justify: singleStepJustify, gap: "sm" }, showCancel && /* @__PURE__ */ React2.createElement(Button2, { variant: "secondary", onClick: onCancel, disabled }, cancelButtonLabel), /* @__PURE__ */ React2.createElement(
3489
3502
  LoadingButton,
3490
3503
  {
3491
3504
  variant: submitVariant,
@@ -5429,7 +5442,7 @@ var KeyValueList = ({ items = [], direction = "row", gap = "sm" }) => {
5429
5442
 
5430
5443
  // src/common-components/SectionHeader.js
5431
5444
  import React10 from "react";
5432
- import { Flex as Flex6, Heading, Text as Text5 } from "@hubspot/ui-extensions";
5445
+ import { Flex as Flex6, Heading as Heading2, Text as Text5 } from "@hubspot/ui-extensions";
5433
5446
  var SectionHeader = ({
5434
5447
  title,
5435
5448
  description,
@@ -5440,7 +5453,7 @@ var SectionHeader = ({
5440
5453
  }) => {
5441
5454
  const body = [];
5442
5455
  if (title != null) {
5443
- body.push(React10.createElement(Heading, { key: "title", as: titleAs }, title));
5456
+ body.push(React10.createElement(Heading2, { key: "title", as: titleAs }, title));
5444
5457
  }
5445
5458
  if (description != null) {
5446
5459
  body.push(
package/form.d.ts CHANGED
@@ -17,6 +17,7 @@ export {
17
17
  FormBuilderLabels,
18
18
  FormBuilderAlertConfig,
19
19
  FormBuilderButtonsRenderContext,
20
+ FormBuilderSubmitAlign,
20
21
  FormBuilderLayout,
21
22
  FormBuilderLayoutEntry,
22
23
  FormBuilderSection,
package/index.d.ts CHANGED
@@ -75,6 +75,7 @@ export type {
75
75
  FormBuilderLabels,
76
76
  FormBuilderAlertConfig,
77
77
  FormBuilderButtonsRenderContext,
78
+ FormBuilderSubmitAlign,
78
79
  FormBuilderLayout,
79
80
  FormBuilderLayoutEntry,
80
81
  FormBuilderSection,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hs-uix",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Production-ready UI components for HubSpot UI Extensions — DataTable, FormBuilder, and more",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",