@allxsmith/bestax-bulma 5.8.4 → 5.9.0

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.esm.js CHANGED
@@ -5558,6 +5558,17 @@ const useInsideControl = () => useContext(ControlContext);
5558
5558
  const FieldProvider = FieldContext.Provider;
5559
5559
  /** Provider for Control context — used internally by Control component. */
5560
5560
  const ControlProvider = ControlContext.Provider;
5561
+ const FieldLabelIdContext = createContext(undefined);
5562
+ /**
5563
+ * The id a labeled Field wants its single composed control to adopt (#495).
5564
+ * `undefined` outside a Field, in unlabeled/grouped/addons Fields, or when the
5565
+ * user took over the association with an explicit `labelProps.htmlFor`.
5566
+ * Consumed only by the single-control bases (InputBase, SelectBase,
5567
+ * TextAreaBase). Internal; not part of the public API.
5568
+ */
5569
+ const useFieldLabelId = () => useContext(FieldLabelIdContext);
5570
+ /** Provider for the Field label-target id — used internally by Field. */
5571
+ const FieldLabelIdProvider = FieldLabelIdContext.Provider;
5561
5572
  const RadiosContext = createContext(undefined);
5562
5573
  const CheckboxesContext = createContext(undefined);
5563
5574
  /**
@@ -5765,15 +5776,19 @@ const FieldBody = ({ textColor, bgColor, className, children, ...props }) => {
5765
5776
  * @see {@link https://bulma.io/documentation/form/general/#field | Bulma Field documentation}
5766
5777
  *
5767
5778
  * @example
5768
- * // Labelled field
5779
+ * // Labelled field — the label auto-associates with the composed base
5769
5780
  * <Field label="Email">
5770
- * <input className="input" type="email" />
5781
+ * <Control>
5782
+ * <InputBase type="email" />
5783
+ * </Control>
5771
5784
  * </Field>
5772
5785
  *
5773
5786
  * @example
5774
5787
  * // Horizontal field
5775
5788
  * <Field horizontal label="Name">
5776
- * <input className="input" />
5789
+ * <Control>
5790
+ * <InputBase />
5791
+ * </Control>
5777
5792
  * </Field>
5778
5793
  */
5779
5794
  const FieldComponent = ({ horizontal, grouped, hasAddons, narrow, label, labelSize, labelProps, textColor, color: _fieldColor, bgColor, className, children, ...props }) => {
@@ -5800,13 +5815,24 @@ const FieldComponent = ({ horizontal, grouped, hasAddons, narrow, label, labelSi
5800
5815
  // Default labelSize to 'normal' when horizontal for proper baseline alignment
5801
5816
  const effectiveLabelSize = labelSize ?? (horizontal ? 'normal' : undefined);
5802
5817
  const labelClass = usePrefixedClassNames('label');
5818
+ // Auto-associate the label with a single composed base control (#495): the
5819
+ // label points at a generated id shared via context, which InputBase/
5820
+ // SelectBase/TextAreaBase adopt when the user supplied no id of their own.
5821
+ // Presence semantics on htmlFor — even an explicit `htmlFor: undefined`
5822
+ // means the caller owns the association. Grouped/addons fields hold several
5823
+ // controls, so no single association is generated for them.
5824
+ const generatedId = useId();
5825
+ const userWiredLabel = !!labelProps && 'htmlFor' in labelProps;
5826
+ const targetId = label && !userWiredLabel && !grouped && !hasAddons
5827
+ ? generatedId
5828
+ : undefined;
5803
5829
  let renderedLabel = null;
5804
5830
  if (label) {
5805
5831
  if (horizontal) {
5806
- renderedLabel = (jsx(FieldLabel, { size: effectiveLabelSize, children: jsx("label", { ...labelProps, className: classNames(labelClass, labelProps?.className), style: labelProps?.style, children: label }) }));
5832
+ renderedLabel = (jsx(FieldLabel, { size: effectiveLabelSize, children: jsx("label", { htmlFor: targetId, ...labelProps, className: classNames(labelClass, labelProps?.className), style: labelProps?.style, children: label }) }));
5807
5833
  }
5808
5834
  else {
5809
- renderedLabel = (jsx("label", { ...labelProps, className: classNames(labelClass, labelProps?.className), style: { display: 'block', ...(labelProps?.style || {}) }, children: label }));
5835
+ renderedLabel = (jsx("label", { htmlFor: targetId, ...labelProps, className: classNames(labelClass, labelProps?.className), style: { display: 'block', ...(labelProps?.style || {}) }, children: label }));
5810
5836
  }
5811
5837
  }
5812
5838
  // If horizontal, wrap children in FieldBody (unless the user already provided
@@ -5829,7 +5855,7 @@ const FieldComponent = ({ horizontal, grouped, hasAddons, narrow, label, labelSi
5829
5855
  content = jsx(FieldBody, { children: children });
5830
5856
  }
5831
5857
  }
5832
- return (jsx(FieldProvider, { value: true, children: jsxs("div", { className: fieldClass, ...rest, children: [renderedLabel, content] }) }));
5858
+ return (jsx(FieldProvider, { value: true, children: jsx(FieldLabelIdProvider, { value: targetId, children: jsxs("div", { className: fieldClass, ...rest, children: [renderedLabel, content] }) }) }));
5833
5859
  };
5834
5860
  FieldLabel.displayName = 'FieldLabel';
5835
5861
  FieldBody.displayName = 'FieldBody';
@@ -5843,18 +5869,28 @@ const Field = withSubComponents(FieldComponent, {
5843
5869
  * Associates the convenience `label` prop with its control (#368): generates
5844
5870
  * an id for the control and returns labelProps carrying a matching `htmlFor`.
5845
5871
  * A user-supplied `id` is used as the target instead of the generated one, and
5846
- * an explicit `labelProps.htmlFor` disables generation entirely — the user has
5847
- * taken over the association. Internal; not part of the public API.
5872
+ * an explicit `htmlFor` key in labelProps — even set to `undefined` — disables
5873
+ * generation entirely: the user has taken over the association (#495 presence
5874
+ * semantics). Internal; not part of the public API.
5848
5875
  */
5849
5876
  function useAutoLabelId({ label, id, labelProps, rendersLabel, }) {
5850
5877
  // Called unconditionally per the rules of hooks; SSR-safe on React 18 and 19.
5851
5878
  const generatedId = useId();
5852
5879
  // Truthiness mirrors Field's own `if (label)` render gate.
5853
5880
  const active = !!label && rendersLabel;
5854
- const controlId = id ?? (active && !labelProps?.htmlFor ? generatedId : undefined);
5881
+ // Presence, not truthiness: `htmlFor: undefined` is an explicit opt-out and
5882
+ // must not leave an orphan generated id on the control.
5883
+ const userWired = !!labelProps && 'htmlFor' in labelProps;
5884
+ const controlId = id ?? (active && !userWired ? generatedId : undefined);
5885
+ // Inactive with a label still means an own Field may render it (pickers'
5886
+ // inline mode, Taginput at maxTags) — the explicit `htmlFor: undefined`
5887
+ // tells Field the association is owned here, so it must not generate one
5888
+ // that would dangle (#495 presence semantics).
5855
5889
  const fieldLabelProps = active
5856
5890
  ? { htmlFor: controlId, ...labelProps }
5857
- : labelProps;
5891
+ : label
5892
+ ? { htmlFor: undefined, ...labelProps }
5893
+ : labelProps;
5858
5894
  return { controlId, fieldLabelProps };
5859
5895
  }
5860
5896
  /**
@@ -7666,6 +7702,7 @@ const InputBase = forwardRef(({ color, size, isRounded, isStatic, isHovered, isF
7666
7702
  color,
7667
7703
  ...props,
7668
7704
  });
7705
+ const fieldLabelId = useFieldLabelId();
7669
7706
  const mainClass = usePrefixedClassNames('input', {
7670
7707
  [`is-${color}`]: !!color,
7671
7708
  [`is-${size}`]: !!size,
@@ -7676,7 +7713,10 @@ const InputBase = forwardRef(({ color, size, isRounded, isStatic, isHovered, isF
7676
7713
  'is-loading': isLoading,
7677
7714
  });
7678
7715
  const inputClass = classNames(mainClass, bulmaHelperClasses, className);
7679
- return (jsx("input", { ref: ref, className: inputClass, disabled: disabled, readOnly: readOnly, ...rest }));
7716
+ return (jsx("input", { ref: ref, className: inputClass, disabled: disabled, readOnly: readOnly, ...rest,
7717
+ // After the spread: a labeled Field's generated id is adopted only
7718
+ // when no user id arrived (rest.id may be an undefined own key).
7719
+ id: rest.id ?? fieldLabelId }));
7680
7720
  });
7681
7721
  InputBase.displayName = 'InputBase';
7682
7722
 
@@ -7693,6 +7733,7 @@ const SelectBase = forwardRef(({ color, size, isRounded, isLoading, isActive, is
7693
7733
  color,
7694
7734
  ...props,
7695
7735
  });
7736
+ const fieldLabelId = useFieldLabelId();
7696
7737
  const mainClass = usePrefixedClassNames('select', {
7697
7738
  [`is-${color}`]: !!color,
7698
7739
  [`is-${size}`]: !!size,
@@ -7717,7 +7758,10 @@ const SelectBase = forwardRef(({ color, size, isRounded, isLoading, isActive, is
7717
7758
  if (multiple && typeof multipleSize === 'number') {
7718
7759
  selectProps.size = multipleSize;
7719
7760
  }
7720
- return (jsx("div", { className: selectClass, children: jsx("select", { ref: ref, className: innerSelectClass || undefined, ...selectProps, children: children }) }));
7761
+ return (jsx("div", { className: selectClass, children: jsx("select", { ref: ref, className: innerSelectClass || undefined, ...selectProps,
7762
+ // After the spread: a labeled Field's generated id is adopted only
7763
+ // when no user id arrived; the id belongs on the inner <select>.
7764
+ id: selectProps.id ?? fieldLabelId, children: children }) }));
7721
7765
  });
7722
7766
  SelectBase.displayName = 'SelectBase';
7723
7767
 
@@ -7734,6 +7778,7 @@ const TextAreaBase = forwardRef(({ color, size, isRounded, isStatic, isHovered,
7734
7778
  color,
7735
7779
  ...props,
7736
7780
  });
7781
+ const fieldLabelId = useFieldLabelId();
7737
7782
  // Note: `is-loading` is intentionally NOT applied to the <textarea> itself —
7738
7783
  // Bulma documents `<div class="control is-loading">` as the loading pattern
7739
7784
  // for textareas, not `<textarea class="textarea is-loading">`. The convenience
@@ -7749,7 +7794,10 @@ const TextAreaBase = forwardRef(({ color, size, isRounded, isStatic, isHovered,
7749
7794
  'has-fixed-size': hasFixedSize,
7750
7795
  });
7751
7796
  const textareaClass = classNames(mainClass, bulmaHelperClasses, className);
7752
- return (jsx("textarea", { ref: ref, className: textareaClass, disabled: disabled, readOnly: readOnly, rows: rows, ...rest }));
7797
+ return (jsx("textarea", { ref: ref, className: textareaClass, disabled: disabled, readOnly: readOnly, rows: rows, ...rest,
7798
+ // After the spread: a labeled Field's generated id is adopted only
7799
+ // when no user id arrived (rest.id may be an undefined own key).
7800
+ id: rest.id ?? fieldLabelId }));
7753
7801
  });
7754
7802
  TextAreaBase.displayName = 'TextAreaBase';
7755
7803