@bubo-squared/ui-framework 0.2.20 → 0.2.22

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/index.cjs CHANGED
@@ -151,10 +151,10 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
151
151
  ]
152
152
  },
153
153
  size: {
154
- sm: ["px-2", "py-1", "gap-2", "h-9"],
155
- md: ["px-2", "py-1", "gap-2", "h-10"],
156
- lg: ["px-2.5", "py-1", "gap-2.5", "h-11"],
157
- xl: ["px-3", "py-0.5", "gap-3", "h-12"]
154
+ sm: ["px-3", "py-1", "gap-2", "h-9"],
155
+ md: ["px-4", "py-2", "gap-2", "h-10"],
156
+ lg: ["px-4", "py-2", "gap-2.5", "h-11"],
157
+ xl: ["px-4", "py-2", "gap-3", "h-12"]
158
158
  }
159
159
  },
160
160
  defaultVariants: {
@@ -774,13 +774,14 @@ var Badge = React9.forwardRef(
774
774
  ...rest
775
775
  } = props;
776
776
  const Comp = asChild ? import_react_slot5.Slot : "div";
777
+ const hasValue = typeof value === "string" ? value.trim() !== "" : value != null;
777
778
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
778
779
  Comp,
779
780
  {
780
781
  ref,
781
782
  className: cn(badgeVariants({ size, variant }), className),
782
783
  ...rest,
783
- children: value ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
784
+ children: hasValue ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
784
785
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-normal", children: label }),
785
786
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-normal", children: ":" }),
786
787
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-medium", children: value })
@@ -961,7 +962,7 @@ var Divider = (props) => {
961
962
  className: _className,
962
963
  ...divProps
963
964
  } = props;
964
- const textLabel = label ? label : "OR";
965
+ const textLabel = label ?? "OR";
965
966
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
966
967
  "div",
967
968
  {
@@ -1109,13 +1110,15 @@ var Field = (props) => {
1109
1110
  className,
1110
1111
  children
1111
1112
  } = props;
1113
+ const hasLabel = label != null;
1114
+ const hasHint = hint != null;
1112
1115
  const fieldId = React14.useId();
1113
- const labelId = label ? `${fieldId}-label` : void 0;
1114
- const hintId = hint ? `${fieldId}-hint` : void 0;
1116
+ const labelId = hasLabel ? `${fieldId}-label` : void 0;
1117
+ const hintId = hasHint ? `${fieldId}-hint` : void 0;
1115
1118
  const hintColorClass = disabled ? "text-primary-disabled" : status === "success" ? "text-(--color-success)" : status === "error" ? "text-(--color-error)" : "text-(--color-secondary)";
1116
1119
  const labelColorClass = disabled ? "text-primary-disabled" : "text-primary";
1117
1120
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: cn(fieldBase, className), children: [
1118
- label && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex w-full items-center justify-between", children: [
1121
+ hasLabel && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex w-full items-center justify-between", children: [
1119
1122
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { id: labelId, className: cn("paragraph-sm", labelColorClass), children: label }),
1120
1123
  labelRight
1121
1124
  ] }),
@@ -1123,9 +1126,9 @@ var Field = (props) => {
1123
1126
  !hideHint && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1124
1127
  "p",
1125
1128
  {
1126
- id: hint ? hintId : void 0,
1127
- className: cn("caption", hint ? hintColorClass : "invisible"),
1128
- children: hint || "\xA0"
1129
+ id: hasHint ? hintId : void 0,
1130
+ className: cn("caption", hasHint ? hintColorClass : "invisible"),
1131
+ children: hasHint ? hint : "\xA0"
1129
1132
  }
1130
1133
  )
1131
1134
  ] });
@@ -1145,6 +1148,7 @@ var Progress = React15.forwardRef(
1145
1148
  value,
1146
1149
  label,
1147
1150
  hint,
1151
+ ariaLabel,
1148
1152
  showProgressLabel = true,
1149
1153
  hideHint,
1150
1154
  size = "lg",
@@ -1155,12 +1159,13 @@ var Progress = React15.forwardRef(
1155
1159
  } = props;
1156
1160
  const clamped = Number.isFinite(value) ? Math.min(100, Math.max(0, value)) : 0;
1157
1161
  const percentageLabel = `${Math.round(clamped)}%`;
1162
+ const resolvedAriaLabel = ariaLabel ?? (typeof label === "string" ? label : void 0);
1158
1163
  const barHeightClasses = sizeToBarClasses[size];
1159
1164
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1160
1165
  Field,
1161
1166
  {
1162
1167
  label,
1163
- labelRight: showProgressLabel && label ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "footnote text-(--color-secondary)", children: percentageLabel }) : void 0,
1168
+ labelRight: showProgressLabel && label != null ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "footnote text-(--color-secondary)", children: percentageLabel }) : void 0,
1164
1169
  hint,
1165
1170
  hideHint,
1166
1171
  status,
@@ -1174,7 +1179,7 @@ var Progress = React15.forwardRef(
1174
1179
  "aria-valuenow": clamped,
1175
1180
  "aria-valuemin": 0,
1176
1181
  "aria-valuemax": 100,
1177
- "aria-label": label,
1182
+ "aria-label": resolvedAriaLabel,
1178
1183
  ...rest,
1179
1184
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1180
1185
  "div",
@@ -1275,7 +1280,7 @@ var import_react_slot6 = require("@radix-ui/react-slot");
1275
1280
  var import_class_variance_authority11 = require("class-variance-authority");
1276
1281
  var import_jsx_runtime19 = require("react/jsx-runtime");
1277
1282
  var tagVariants = (0, import_class_variance_authority11.cva)(
1278
- "inline-flex flex-row items-center justify-center rounded-6 gap-2 px-3 overflow-hidden border-1 border-(--border-secondary) bg-(--background-neutral) hover:border-(--border-secondary-hover) focus:border-(--border-brand) focus-ring-primary ",
1283
+ "inline-flex flex-row items-center justify-center rounded-6 gap-2 px-3 overflow-hidden border-1 border-(--border-secondary) bg-(--background-neutral) focus:border-(--border-brand) focus-ring-primary ",
1279
1284
  {
1280
1285
  variants: {
1281
1286
  size: {
@@ -1301,6 +1306,7 @@ var Tag = React17.forwardRef(
1301
1306
  value,
1302
1307
  ...rest
1303
1308
  } = props;
1309
+ const hasValue = typeof value === "string" ? value.trim() !== "" : value != null;
1304
1310
  const Comp = asChild ? import_react_slot6.Slot : "div";
1305
1311
  const leading = props.leadingIcon && React17.isValidElement(props.leadingIcon) ? React17.cloneElement(props.leadingIcon, { disabled, ...props.leadingIcon.props }) : null;
1306
1312
  const trailing = props.trailingIcon && React17.isValidElement(props.trailingIcon) ? React17.cloneElement(props.trailingIcon, { disabled, ...props.trailingIcon.props }) : null;
@@ -1312,7 +1318,7 @@ var Tag = React17.forwardRef(
1312
1318
  ...rest,
1313
1319
  children: [
1314
1320
  leading && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: iconClasses, children: leading }),
1315
- value ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-row gap-1 items-center", children: [
1321
+ hasValue ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-row gap-1 items-center", children: [
1316
1322
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-primary paragraph-lg mb-0! cursor-default font-normal", children: label }),
1317
1323
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-primary paragraph-lg mb-0! cursor-default font-normal", children: ":" }),
1318
1324
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-primary paragraph-lg-medium mb-0! cursor-default font-medium", children: value })
@@ -1583,16 +1589,17 @@ var MenuSubContent = DropdownMenuSubContent;
1583
1589
  var MenuSubTrigger = DropdownMenuSubTrigger;
1584
1590
 
1585
1591
  // src/components/Inputs/Checkbox.tsx
1586
- var React20 = require("react");
1592
+ var React20 = __toESM(require("react"), 1);
1587
1593
  var CheckboxPrimitive = __toESM(require("@radix-ui/react-checkbox"), 1);
1588
1594
  var import_icons6 = require("@bubo-squared/icons");
1589
1595
  var import_icons7 = require("@bubo-squared/icons");
1590
1596
  var import_jsx_runtime22 = require("react/jsx-runtime");
1591
- function Checkbox({ label, className, ...props }) {
1597
+ var Checkbox = React20.forwardRef(({ label, className, ...props }, forwardedRef) => {
1592
1598
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "inline-flex items-center gap-(--space-12) cursor-pointer select-none", children: [
1593
1599
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1594
1600
  CheckboxPrimitive.Root,
1595
1601
  {
1602
+ ref: forwardedRef,
1596
1603
  className: cn(
1597
1604
  "group flex h-5 w-5 items-center justify-center rounded-2 border border-(--border-secondary) bg-(--background-neutral) text-primary-inverse",
1598
1605
  "data-[state=checked]:bg-(--background-brand) data-[state=checked]:text-button-white data-[state=checked]:border-none",
@@ -1614,7 +1621,8 @@ function Checkbox({ label, className, ...props }) {
1614
1621
  ),
1615
1622
  label && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "paragraph-md-medium text-primary", children: label })
1616
1623
  ] });
1617
- }
1624
+ });
1625
+ Checkbox.displayName = "Checkbox";
1618
1626
 
1619
1627
  // src/components/Inputs/Autocomplete.tsx
1620
1628
  var React23 = __toESM(require("react"), 1);
@@ -1747,7 +1755,7 @@ var iconWrapperVariants = (0, import_class_variance_authority14.cva)(
1747
1755
  }
1748
1756
  }
1749
1757
  );
1750
- var Autocomplete = (props) => {
1758
+ var Autocomplete = React23.forwardRef((props, forwardedRef) => {
1751
1759
  const {
1752
1760
  label,
1753
1761
  hint,
@@ -1768,6 +1776,7 @@ var Autocomplete = (props) => {
1768
1776
  inputValue,
1769
1777
  defaultInputValue,
1770
1778
  onInputChange,
1779
+ freeSolo = false,
1771
1780
  dropdownClassName,
1772
1781
  listboxClassName,
1773
1782
  placeholder = "Search\u2026",
@@ -1788,6 +1797,18 @@ var Autocomplete = (props) => {
1788
1797
  const [isFocused, setIsFocused] = React23.useState(false);
1789
1798
  const [activeIndex, setActiveIndex] = React23.useState(-1);
1790
1799
  const inputRef = React23.useRef(null);
1800
+ const setInputRef = React23.useCallback(
1801
+ (node) => {
1802
+ inputRef.current = node;
1803
+ if (!forwardedRef) return;
1804
+ if (typeof forwardedRef === "function") {
1805
+ forwardedRef(node);
1806
+ } else {
1807
+ forwardedRef.current = node;
1808
+ }
1809
+ },
1810
+ [forwardedRef]
1811
+ );
1791
1812
  const baseId = React23.useId();
1792
1813
  const inputId = id ?? baseId;
1793
1814
  const listboxId = `${inputId}-listbox`;
@@ -1806,6 +1827,12 @@ var Autocomplete = (props) => {
1806
1827
  }
1807
1828
  onInputChange?.(next);
1808
1829
  };
1830
+ const commitTypedValue = (next) => {
1831
+ if (!isValueControlled) {
1832
+ setInternalValue(next);
1833
+ }
1834
+ onChange?.(next);
1835
+ };
1809
1836
  const commitValue = (next) => {
1810
1837
  if (!isValueControlled) {
1811
1838
  setInternalValue(next);
@@ -1822,6 +1849,9 @@ var Autocomplete = (props) => {
1822
1849
  const next = event.target.value;
1823
1850
  setInputText(next);
1824
1851
  setActiveIndex(-1);
1852
+ if (freeSolo) {
1853
+ commitTypedValue(next);
1854
+ }
1825
1855
  };
1826
1856
  const handleFocus = (event) => {
1827
1857
  setIsFocused(true);
@@ -1830,6 +1860,12 @@ var Autocomplete = (props) => {
1830
1860
  const handleBlur = (event) => {
1831
1861
  setIsFocused(false);
1832
1862
  setActiveIndex(-1);
1863
+ if (freeSolo) {
1864
+ const trimmed = currentInput.trim();
1865
+ if (trimmed.length > 0 && currentInput !== currentValue) {
1866
+ commitTypedValue(currentInput);
1867
+ }
1868
+ }
1833
1869
  onBlur?.(event);
1834
1870
  };
1835
1871
  const handleKeyDown = (event) => {
@@ -1863,6 +1899,17 @@ var Autocomplete = (props) => {
1863
1899
  event.preventDefault();
1864
1900
  commitValue(options[activeIndex]);
1865
1901
  setIsFocused(false);
1902
+ break;
1903
+ }
1904
+ if (freeSolo) {
1905
+ const trimmed = currentInput.trim();
1906
+ if (trimmed.length > 0) {
1907
+ event.preventDefault();
1908
+ if (currentInput !== currentValue) {
1909
+ commitTypedValue(currentInput);
1910
+ }
1911
+ setIsFocused(false);
1912
+ }
1866
1913
  }
1867
1914
  break;
1868
1915
  }
@@ -1900,7 +1947,7 @@ var Autocomplete = (props) => {
1900
1947
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1901
1948
  Input,
1902
1949
  {
1903
- ref: inputRef,
1950
+ ref: setInputRef,
1904
1951
  id: inputId,
1905
1952
  type: "text",
1906
1953
  disabled: disabled ?? void 0,
@@ -1975,7 +2022,7 @@ var Autocomplete = (props) => {
1975
2022
  }
1976
2023
  )
1977
2024
  ] }) });
1978
- };
2025
+ });
1979
2026
  Autocomplete.displayName = "Autocomplete";
1980
2027
 
1981
2028
  // src/components/Inputs/Select.tsx
@@ -2058,7 +2105,7 @@ var selectButtonVariants = (0, import_class_variance_authority15.cva)(
2058
2105
  }
2059
2106
  }
2060
2107
  );
2061
- var Select = (props) => {
2108
+ var Select = React24.forwardRef((props, forwardedRef) => {
2062
2109
  const {
2063
2110
  label = "Field Label",
2064
2111
  hint = "This is a hint text to help user.",
@@ -2133,6 +2180,7 @@ var Select = (props) => {
2133
2180
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SelectPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
2134
2181
  "button",
2135
2182
  {
2183
+ ref: forwardedRef,
2136
2184
  type: "button",
2137
2185
  "aria-haspopup": "listbox",
2138
2186
  "aria-expanded": isOpen,
@@ -2207,7 +2255,7 @@ var Select = (props) => {
2207
2255
  )
2208
2256
  }
2209
2257
  );
2210
- };
2258
+ });
2211
2259
  Select.displayName = "Select";
2212
2260
 
2213
2261
  // src/components/Inputs/PasswordInput.tsx
@@ -2271,7 +2319,7 @@ var actionButtonVariants = (0, import_class_variance_authority16.cva)(
2271
2319
  }
2272
2320
  }
2273
2321
  );
2274
- var PasswordInput = (props) => {
2322
+ var PasswordInput = React25.forwardRef((props, forwardedRef) => {
2275
2323
  const {
2276
2324
  label,
2277
2325
  hint,
@@ -2295,6 +2343,18 @@ var PasswordInput = (props) => {
2295
2343
  const [isRevealed, setIsRevealed] = React25.useState(false);
2296
2344
  const currentValue = (isControlled ? value : internalValue) ?? "";
2297
2345
  const inputRef = React25.useRef(null);
2346
+ const setInputRef = React25.useCallback(
2347
+ (node) => {
2348
+ inputRef.current = node;
2349
+ if (!forwardedRef) return;
2350
+ if (typeof forwardedRef === "function") {
2351
+ forwardedRef(node);
2352
+ } else {
2353
+ forwardedRef.current = node;
2354
+ }
2355
+ },
2356
+ [forwardedRef]
2357
+ );
2298
2358
  const showLeadingIcon = !!leadingIcon;
2299
2359
  const handleContainerClick = () => {
2300
2360
  if (disabled) return;
@@ -2335,7 +2395,7 @@ var PasswordInput = (props) => {
2335
2395
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2336
2396
  Input,
2337
2397
  {
2338
- ref: inputRef,
2398
+ ref: setInputRef,
2339
2399
  type: isRevealed ? "text" : "password",
2340
2400
  disabled: disabled ?? void 0,
2341
2401
  placeholder,
@@ -2370,7 +2430,7 @@ var PasswordInput = (props) => {
2370
2430
  )
2371
2431
  }
2372
2432
  );
2373
- };
2433
+ });
2374
2434
  PasswordInput.displayName = "PasswordInput";
2375
2435
 
2376
2436
  // src/components/Inputs/PhoneInput.tsx
@@ -3017,19 +3077,20 @@ var FlagComponent = ({ country, countryName }) => {
3017
3077
  var React32 = __toESM(require("react"), 1);
3018
3078
  var RadioGroupPrimitive = __toESM(require("@radix-ui/react-radio-group"), 1);
3019
3079
  var import_jsx_runtime34 = require("react/jsx-runtime");
3020
- var RadioGroup = ({
3021
- label,
3022
- hint,
3023
- hideHint,
3024
- options,
3025
- orientation = "vertical",
3026
- disabled = false,
3027
- value,
3028
- defaultValue,
3029
- onValueChange,
3030
- className,
3031
- ...rootProps
3032
- }) => {
3080
+ var RadioGroup = React32.forwardRef((props, forwardedRef) => {
3081
+ const {
3082
+ label,
3083
+ hint,
3084
+ hideHint,
3085
+ options,
3086
+ orientation = "vertical",
3087
+ disabled = false,
3088
+ value,
3089
+ defaultValue,
3090
+ onValueChange,
3091
+ className,
3092
+ ...rootProps
3093
+ } = props;
3033
3094
  const groupId = React32.useId();
3034
3095
  const hintId = hint ? `${groupId}-hint` : void 0;
3035
3096
  const handleValueChange = (next) => {
@@ -3046,6 +3107,7 @@ var RadioGroup = ({
3046
3107
  children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3047
3108
  RadioGroupPrimitive.Root,
3048
3109
  {
3110
+ ref: forwardedRef,
3049
3111
  ...rootProps,
3050
3112
  value,
3051
3113
  defaultValue,
@@ -3126,7 +3188,8 @@ var RadioGroup = ({
3126
3188
  )
3127
3189
  }
3128
3190
  );
3129
- };
3191
+ });
3192
+ RadioGroup.displayName = "RadioGroup";
3130
3193
 
3131
3194
  // src/components/Inputs/SearchInput.tsx
3132
3195
  var React33 = __toESM(require("react"), 1);
@@ -3162,7 +3225,7 @@ var iconWrapperVariants3 = (0, import_class_variance_authority19.cva)("flex item
3162
3225
  size: "lg"
3163
3226
  }
3164
3227
  });
3165
- var SearchInput = (props) => {
3228
+ var SearchInput = React33.forwardRef((props, forwardedRef) => {
3166
3229
  const {
3167
3230
  placeholder = "Search...",
3168
3231
  size = "lg",
@@ -3174,6 +3237,18 @@ var SearchInput = (props) => {
3174
3237
  ...inputProps
3175
3238
  } = props;
3176
3239
  const inputRef = React33.useRef(null);
3240
+ const setInputRef = React33.useCallback(
3241
+ (node) => {
3242
+ inputRef.current = node;
3243
+ if (!forwardedRef) return;
3244
+ if (typeof forwardedRef === "function") {
3245
+ forwardedRef(node);
3246
+ } else {
3247
+ forwardedRef.current = node;
3248
+ }
3249
+ },
3250
+ [forwardedRef]
3251
+ );
3177
3252
  const handleContainerClick = () => {
3178
3253
  if (disabled) return;
3179
3254
  inputRef.current?.focus();
@@ -3192,7 +3267,7 @@ var SearchInput = (props) => {
3192
3267
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3193
3268
  Input,
3194
3269
  {
3195
- ref: inputRef,
3270
+ ref: setInputRef,
3196
3271
  type: "search",
3197
3272
  placeholder,
3198
3273
  disabled: disabled ?? void 0,
@@ -3207,7 +3282,7 @@ var SearchInput = (props) => {
3207
3282
  ]
3208
3283
  }
3209
3284
  ) }) });
3210
- };
3285
+ });
3211
3286
  SearchInput.displayName = "SearchInput";
3212
3287
 
3213
3288
  // src/components/Inputs/Slider.tsx
@@ -3264,6 +3339,8 @@ var Tooltip = (props) => {
3264
3339
  children,
3265
3340
  delayDuration = 200
3266
3341
  } = props;
3342
+ const hasStrapline = typeof strapline === "string" ? strapline.trim() !== "" : strapline != null;
3343
+ const hasDescription = typeof description === "string" ? description.trim() !== "" : description != null;
3267
3344
  const { side, align } = mapPlacementToSideAndAlign(placement);
3268
3345
  const tooltipClasses = "group bg-(--background-tooltip) max-w-[calc(100vw-2rem)] shadow-card-md border-none rounded-4 py-1.5 px-2.5 [&>span]:scale-200 data-[state=delayed-open]:animate-in data-[state=instant-open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=delayed-open]:fade-in-0 data-[state=instant-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2";
3269
3346
  const tooltipArrowClasses = "relative fill-(--background-tooltip) transition-[filter,transform] group-data-[side=top]:top-[-2px] group-data-[side=top]:drop-shadow-[0px_1px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)] group-data-[side=bottom]:drop-shadow-[0px_1px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)] group-data-[side=left]:drop-shadow-[0px_2px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)] group-data-[side=right]:drop-shadow-[0px_2px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)]";
@@ -3287,9 +3364,9 @@ var Tooltip = (props) => {
3287
3364
  children: [
3288
3365
  showArrow && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TooltipArrow, { className: tooltipArrowClasses }),
3289
3366
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "grid", children: [
3290
- (strapline ?? "") !== "" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "caption text-secondary", children: strapline }),
3367
+ hasStrapline && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "caption text-secondary", children: strapline }),
3291
3368
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h4", { className: "paragraph-md text-primary", children: title }),
3292
- (description ?? "") !== "" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "paragraph-sm text-primary", children: description })
3369
+ hasDescription && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "paragraph-sm text-primary", children: description })
3293
3370
  ] })
3294
3371
  ]
3295
3372
  }
@@ -3310,7 +3387,7 @@ var toArray = (value) => {
3310
3387
  if (value === void 0) return void 0;
3311
3388
  return Array.isArray(value) ? value : [value];
3312
3389
  };
3313
- var Slider = (props) => {
3390
+ var Slider = React35.forwardRef((props, forwardedRef) => {
3314
3391
  const {
3315
3392
  name,
3316
3393
  display = "flat",
@@ -3626,6 +3703,7 @@ var Slider = (props) => {
3626
3703
  {
3627
3704
  className: wrapperBase,
3628
3705
  style: { marginInline: `${thumbRadius}px` },
3706
+ ref: forwardedRef,
3629
3707
  children: [
3630
3708
  name && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
3631
3709
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
@@ -3691,14 +3769,14 @@ var Slider = (props) => {
3691
3769
  ]
3692
3770
  }
3693
3771
  );
3694
- };
3772
+ });
3695
3773
  Slider.displayName = "Slider";
3696
3774
 
3697
3775
  // src/components/Inputs/TextArea.tsx
3698
3776
  var React36 = __toESM(require("react"), 1);
3699
3777
  var import_icons13 = require("@bubo-squared/icons");
3700
3778
  var import_jsx_runtime38 = require("react/jsx-runtime");
3701
- var TextArea = (props) => {
3779
+ var TextArea = React36.forwardRef((props, forwardedRef) => {
3702
3780
  const {
3703
3781
  label,
3704
3782
  hint,
@@ -3727,6 +3805,18 @@ var TextArea = (props) => {
3727
3805
  const showCharacterLimit = type === "character-limit" && typeof effectiveMaxLength === "number";
3728
3806
  const textareaRef = React36.useRef(null);
3729
3807
  const containerRef = React36.useRef(null);
3808
+ const setTextareaRef = React36.useCallback(
3809
+ (node) => {
3810
+ textareaRef.current = node;
3811
+ if (!forwardedRef) return;
3812
+ if (typeof forwardedRef === "function") {
3813
+ forwardedRef(node);
3814
+ } else {
3815
+ forwardedRef.current = node;
3816
+ }
3817
+ },
3818
+ [forwardedRef]
3819
+ );
3730
3820
  const [height, setHeight] = React36.useState(void 0);
3731
3821
  const [width, setWidth] = React36.useState(void 0);
3732
3822
  const minHeight = 80;
@@ -3811,7 +3901,7 @@ var TextArea = (props) => {
3811
3901
  {
3812
3902
  id: textareaId,
3813
3903
  name,
3814
- ref: textareaRef,
3904
+ ref: setTextareaRef,
3815
3905
  disabled: disabled ?? void 0,
3816
3906
  value: isControlled ? value : currentValue,
3817
3907
  defaultValue: isControlled ? void 0 : defaultValue,
@@ -3862,7 +3952,7 @@ var TextArea = (props) => {
3862
3952
  )
3863
3953
  }
3864
3954
  );
3865
- };
3955
+ });
3866
3956
  TextArea.displayName = "TextArea";
3867
3957
 
3868
3958
  // src/components/Inputs/TextInput.tsx
@@ -3901,7 +3991,7 @@ var iconWrapperVariants4 = (0, import_class_variance_authority20.cva)(
3901
3991
  }
3902
3992
  }
3903
3993
  );
3904
- var TextInput = (props) => {
3994
+ var TextInput = React37.forwardRef((props, forwardedRef) => {
3905
3995
  const {
3906
3996
  label,
3907
3997
  hint,
@@ -3924,6 +4014,18 @@ var TextInput = (props) => {
3924
4014
  );
3925
4015
  const currentValue = (isControlled ? value : internalValue) ?? "";
3926
4016
  const inputRef = React37.useRef(null);
4017
+ const setInputRef = React37.useCallback(
4018
+ (node) => {
4019
+ inputRef.current = node;
4020
+ if (!forwardedRef) return;
4021
+ if (typeof forwardedRef === "function") {
4022
+ forwardedRef(node);
4023
+ } else {
4024
+ forwardedRef.current = node;
4025
+ }
4026
+ },
4027
+ [forwardedRef]
4028
+ );
3927
4029
  const handleContainerClick = () => {
3928
4030
  if (disabled) return;
3929
4031
  inputRef.current?.focus();
@@ -3965,7 +4067,7 @@ var TextInput = (props) => {
3965
4067
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3966
4068
  Input,
3967
4069
  {
3968
- ref: inputRef,
4070
+ ref: setInputRef,
3969
4071
  type: "text",
3970
4072
  disabled: disabled ?? void 0,
3971
4073
  placeholder,
@@ -3994,13 +4096,13 @@ var TextInput = (props) => {
3994
4096
  )
3995
4097
  }
3996
4098
  );
3997
- };
4099
+ });
3998
4100
  TextInput.displayName = "TextInput";
3999
4101
 
4000
4102
  // src/components/Inputs/Toggle.tsx
4001
- var React38 = require("react");
4103
+ var React38 = __toESM(require("react"), 1);
4002
4104
  var import_jsx_runtime40 = require("react/jsx-runtime");
4003
- var Toggle = (props) => {
4105
+ var Toggle = React38.forwardRef((props, forwardedRef) => {
4004
4106
  const { label, className, disabled, ...inputProps } = props;
4005
4107
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
4006
4108
  "label",
@@ -4014,6 +4116,7 @@ var Toggle = (props) => {
4014
4116
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
4015
4117
  "input",
4016
4118
  {
4119
+ ref: forwardedRef,
4017
4120
  type: "checkbox",
4018
4121
  disabled,
4019
4122
  className: "peer sr-only",
@@ -4085,13 +4188,13 @@ var Toggle = (props) => {
4085
4188
  ]
4086
4189
  }
4087
4190
  );
4088
- };
4191
+ });
4089
4192
  Toggle.displayName = "Toggle";
4090
4193
 
4091
4194
  // src/components/Inputs/WebsiteInput.tsx
4092
- var React39 = require("react");
4195
+ var React39 = __toESM(require("react"), 1);
4093
4196
  var import_jsx_runtime41 = require("react/jsx-runtime");
4094
- var WebsiteInput = (props) => {
4197
+ var WebsiteInput = React39.forwardRef((props, forwardedRef) => {
4095
4198
  const {
4096
4199
  hierarchy = "leading",
4097
4200
  protocolLabel = "http://",
@@ -4138,6 +4241,7 @@ var WebsiteInput = (props) => {
4138
4241
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4139
4242
  TextInput,
4140
4243
  {
4244
+ ref: forwardedRef,
4141
4245
  ...rest,
4142
4246
  size,
4143
4247
  disabled,
@@ -4146,7 +4250,7 @@ var WebsiteInput = (props) => {
4146
4250
  trailingIcon: !isLeading ? trailingAddon : void 0
4147
4251
  }
4148
4252
  );
4149
- };
4253
+ });
4150
4254
  WebsiteInput.displayName = "WebsiteInput";
4151
4255
 
4152
4256
  // src/components/Feedback/Popover.tsx
@@ -4169,6 +4273,8 @@ var Popover2 = (props) => {
4169
4273
  offset = 10,
4170
4274
  children
4171
4275
  } = props;
4276
+ const hasStrapline = typeof strapline === "string" ? strapline.trim() !== "" : strapline != null;
4277
+ const hasDescription = typeof description === "string" ? description.trim() !== "" : description != null;
4172
4278
  const [open, setOpen] = React40.useState(false);
4173
4279
  const handleCancel = () => {
4174
4280
  onCancel?.();
@@ -4224,9 +4330,9 @@ var Popover2 = (props) => {
4224
4330
  showArrow && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(PopoverArrow, { className: popoverArrowClasses }),
4225
4331
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "grid gap-4", children: [
4226
4332
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-2", children: [
4227
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "caption text-secondary", children: strapline }),
4333
+ hasStrapline && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "caption text-secondary", children: strapline }),
4228
4334
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "subtitle-medium text-primary", children: title }),
4229
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "paragraph-sm text-primary", children: description })
4335
+ hasDescription && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "paragraph-sm text-primary", children: description })
4230
4336
  ] }),
4231
4337
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex justify-start items-center gap-4 flex-wrap", children: [
4232
4338
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Button, { size: "sm", variant: "secondary", onClick: handleCancel, children: cancelText || "Cancel" }),