@allxsmith/bestax-bulma 5.27.5 → 5.27.7
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/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/elements/Notification.js +1 -0
- package/dist/esm/elements/Notification.js.map +1 -1
- package/dist/esm/form/Autocomplete.js +9 -9
- package/dist/esm/form/Autocomplete.js.map +1 -1
- package/dist/esm/form/DateRangeInputBase.js +18 -3
- package/dist/esm/form/DateRangeInputBase.js.map +1 -1
- package/dist/esm/form/Field.js +22 -12
- package/dist/esm/form/Field.js.map +1 -1
- package/dist/esm/form/FormContext.js +18 -13
- package/dist/esm/form/FormContext.js.map +1 -1
- package/dist/esm/form/Slider.js.map +1 -1
- package/dist/esm/form/useAutoLabelId.js +6 -5
- package/dist/esm/form/useAutoLabelId.js.map +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +73 -42
- package/dist/index.cjs.map +1 -1
- package/dist/types/elements/Notification.d.ts +5 -0
- package/dist/types/form/Autocomplete.d.ts +2 -2
- package/dist/types/form/DateRangeInputBase.d.ts +5 -0
- package/dist/types/form/Field.d.ts +8 -3
- package/dist/types/form/FormContext.d.ts +26 -14
- package/dist/types/form/Slider.d.ts +1 -1
- package/dist/types/form/useAutoLabelId.d.ts +7 -5
- package/dist/types-cjs/elements/Notification.d.ts +5 -0
- package/dist/types-cjs/form/Autocomplete.d.ts +2 -2
- package/dist/types-cjs/form/DateRangeInputBase.d.ts +5 -0
- package/dist/types-cjs/form/Field.d.ts +8 -3
- package/dist/types-cjs/form/FormContext.d.ts +26 -14
- package/dist/types-cjs/form/Slider.d.ts +1 -1
- package/dist/types-cjs/form/useAutoLabelId.d.ts +7 -5
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/elements/_index.scss +1 -0
- package/src/scss/elements/_notification.scss +69 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRangeInputBase.js","sources":["../../../src/form/DateRangeInputBase.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {\n DateRangeValue,\n DayOfWeek,\n PickerLabels,\n PickerPosition,\n mergeLabels,\n} from './_pickerInternals/pickerTypes';\nimport {\n DEFAULT_DATE_FORMAT,\n DateFormatOption,\n formatDate,\n fromIsoValue,\n parseDate,\n toIsoValue,\n} from './_pickerInternals/formatters';\nimport {\n canCloseRange,\n clampDate,\n floorMin,\n isSameDay,\n isWithin,\n startOfDay,\n} from './_pickerInternals/dateUtils';\nimport { Calendar, CALENDAR_FOCUSED_CELL } from './_pickerInternals/Calendar';\nimport { PickerPopover } from './_pickerInternals/PickerPopover';\nimport { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker';\nimport { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry';\nimport { useControlLoading } from './controlLoading';\nimport { Icon } from '../elements/Icon';\n\nexport type { DateRangeValue };\n\nconst EMPTY_RANGE: DateRangeValue = [null, null];\n\n/** A range's end as the form and the native inputs carry it. */\nconst isoDay = (d: Date | null): string => (d ? toIsoValue(d, 'day') : '');\n\n/** Today at local midnight, where typing into an empty end starts. */\nconst today = (): Date => startOfDay(new Date());\n\n/**\n * Props for the raw DateRangeInput base. Use the higher-level\n * `DateRangeInput` for Field/Control composition; `DateRangeInputBase` is the\n * two inputs and the popover only.\n */\nexport interface DateRangeInputBaseProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange' | 'color' | 'placeholder' | 'popover'\n >,\n Omit<BulmaClassesProps, 'color'> {\n /**\n * Controlled range, start first. Either end may be `null`, and\n * `[null, null]` is empty.\n */\n value?: DateRangeValue;\n /** Initial range for uncontrolled usage. */\n defaultValue?: DateRangeValue;\n /**\n * Fired when the range changes, with the start first. Typing commits one\n * end at a time, so a range half typed arrives as `[start, null]`. The\n * calendar commits only a finished range: its first pick marks the start\n * inside the calendar and its second commits both ends in one call. The\n * range stays ordered, so the end is never before the start.\n */\n onChange?: (range: DateRangeValue) => void;\n /** Fired when the popover opens. */\n onOpen?: () => void;\n /** Fired when the popover closes. */\n onClose?: () => void;\n /**\n * Earliest selectable date, for either end. A `min` before year 1 is raised\n * to 1 January of year 1, where the range starts without one too.\n */\n min?: Date;\n /** Latest selectable date, for either end. */\n max?: Date;\n /** Disable both inputs and the launcher. */\n disabled?: boolean;\n /** Make both inputs read-only and keep the popover closed. */\n readOnly?: boolean;\n /** Placeholder text, shown in both inputs while they are empty. */\n placeholder?: string;\n /**\n * Token format string or `Intl.DateTimeFormat` options, used by both\n * inputs.\n * @defaultValue 'YYYY-MM-DD'\n */\n format?: DateFormatOption;\n /**\n * Custom parser (use when `format` is `Intl.DateTimeFormatOptions`).\n * Enter and leaving an input call it only if the user changed its text.\n */\n parse?: (s: string) => Date | null;\n /** BCP-47 locale tag for day/month names and Intl formatting. */\n locale?: string;\n /**\n * Render the calendar inline, with no inputs and no popover. The hidden\n * form inputs still carry the range.\n */\n inline?: boolean;\n /**\n * Use two native `<input type=\"date\">`s on coarse-pointer, small-viewport\n * devices (`'auto'`), always (`true`) or never (`false`). The end input's\n * `min` follows the start, and a change goes through the same rules as\n * typing.\n */\n mobileNative?: boolean | 'auto';\n /** Allow segmented keyboard typing in both inputs. `false` makes the field picker-only. */\n editable?: boolean;\n /** Whether the calendar popover exists. `false` makes the field input-only. */\n popover?: boolean;\n /**\n * Open the popover when focus arrives in the field. Moving focus between\n * the two inputs, or back from the launcher, leaves it closed, and so does\n * the focus a closing popover hands back. A click on either input opens it.\n * With it off, the launcher or Alt+ArrowDown opens it.\n */\n openOnFocus?: boolean;\n /**\n * Close the popover once the range is picked. The first pick, which only\n * marks the start, never closes it.\n */\n closeOnSelect?: boolean;\n /** Popover anchor position relative to the field. */\n position?: PickerPosition;\n /** Render the popover into `document.body` via portal. */\n appendToBody?: boolean;\n /**\n * Bulma color modifier for the field, also carried by the calendar, where it\n * colors the range's ends and the band between them.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Render the field with rounded corners. */\n isRounded?: boolean;\n /**\n * Predicate to disable specific dates (e.g. weekends). A disabled day can\n * be neither end, typing rejects it, and a range can't include one unless\n * `allowDisabledInRange` is set.\n */\n shouldDisableDate?: (d: Date) => boolean;\n /** Convenience array of disabled dates; merged with `shouldDisableDate`. Matched by calendar day. */\n unselectableDates?: Date[];\n /**\n * Let a range include days that `shouldDisableDate` or `unselectableDates`\n * disable, such as a stay over a night with no check-ins. Its ends still\n * can't be such days. Off, a pick in the calendar past a disabled day\n * starts a new range there, typing refuses an end past one, and a start\n * typed with one before the end clears the end. Finding one walks the days\n * between, so off, a span too long to walk is refused as well.\n */\n allowDisabledInRange?: boolean;\n /** Day the week starts on (0 = Sunday). */\n firstDayOfWeek?: DayOfWeek;\n /** Override the 7 day-name labels (in calendar order, post-rotation). */\n dayNames?: string[];\n /** Override the 12 month-name labels. */\n monthNames?: string[];\n /** Show dimmed dates from adjacent months in the grid. */\n nearbyMonthDays?: boolean;\n /** Decorative left icon glyph for the wrapping `Control` (shown by default). Set `''` to hide. */\n iconLeftName?: string;\n /**\n * Show a clickable launcher button on the right that toggles the popover.\n * Hidden by default while a `Control` it sits in shows its `isLoading`\n * spinner, which shares that right edge.\n * @defaultValue true\n */\n triggerIcon?: boolean;\n /** Glyph for the right launcher button. */\n triggerIconName?: string;\n /**\n * Optional translatable string overrides. `rangeStart` and `rangeEnd` name\n * the two inputs and the range's ends in the calendar, `rangePreviewEnd`\n * describes the day a pending range would end on, `rangeSeparator` sits\n * between the inputs, and `chooseDateRange` names the launcher and the\n * popover.\n */\n labels?: PickerLabels;\n /**\n * Form field name. Two hidden inputs submit the range as `YYYY-MM-DD`,\n * named `name[start]` and `name[end]`, in every mode. The visible inputs\n * carry no name.\n */\n name?: string;\n /** Name of the hidden input carrying the start, in place of `name[start]`. */\n startName?: string;\n /** Name of the hidden input carrying the end, in place of `name[end]`. */\n endName?: string;\n /** Form id the hidden inputs belong to. */\n form?: string;\n /**\n * Mark both visible inputs required, so a form won't submit with either\n * end empty. An `inline` calendar has no visible input, so it is not\n * checked there.\n */\n required?: boolean;\n /** Id of the start input. The end input takes `${id}-end`. */\n id?: string;\n}\n\n/**\n * Raw DateRangeInput: the two inputs and the popover calendar without\n * Field/Control wrapping. Use `DateRangeInput` for the convenience wrapper.\n *\n * @function\n * @param {DateRangeInputBaseProps} props\n * @returns {JSX.Element}\n */\nexport const DateRangeInputBase = forwardRef<\n HTMLInputElement,\n DateRangeInputBaseProps\n>((props, ref) => {\n const {\n value: controlledValue,\n defaultValue,\n onChange,\n onOpen,\n onClose,\n min,\n max,\n disabled,\n readOnly,\n placeholder,\n format,\n parse,\n locale,\n inline = false,\n mobileNative = 'auto',\n editable = true,\n popover = true,\n openOnFocus = true,\n closeOnSelect = true,\n position = 'bottom-left',\n appendToBody = false,\n color,\n size,\n isRounded,\n shouldDisableDate,\n unselectableDates,\n allowDisabledInRange = false,\n firstDayOfWeek = 0,\n dayNames,\n monthNames,\n nearbyMonthDays = true,\n iconLeftName: _iconLeftName,\n triggerIcon: triggerIconProp,\n triggerIconName = 'chevron-down',\n labels,\n name,\n startName,\n endName,\n form,\n required,\n id,\n className,\n onFocus,\n onFocusCapture,\n ...rest\n } = props;\n // The launcher gives way to the loading spinner of a Control this sits in.\n const controlLoading = useControlLoading();\n const triggerIcon = triggerIconProp ?? !controlLoading;\n\n const t = mergeLabels(labels);\n const resolvedFormat = format ?? DEFAULT_DATE_FORMAT;\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<DateRangeValue>(\n defaultValue ?? EMPTY_RANGE\n );\n const range = isControlled ? controlledValue : internalValue;\n const [start, end] = range;\n\n // Nothing before year 1 is in range, as in HTML's date inputs.\n const lowerBound = useMemo(() => floorMin(min), [min]);\n\n const [focusedDate, setFocusedDate] = useState<Date>(() =>\n clampDate(start ?? end ?? new Date(), lowerBound, max)\n );\n // Re-clamp the focused day if the bounds change after mount, so the\n // calendar never shows a month outside them.\n useEffect(() => {\n setFocusedDate(prev => clampDate(prev, lowerBound, max));\n }, [lowerBound, max]);\n\n const [open, setOpenState] = useState(false);\n const [startText, setStartText] = useState(() =>\n start ? formatDate(start, resolvedFormat, locale) : ''\n );\n const [endText, setEndText] = useState(() =>\n end ? formatDate(end, resolvedFormat, locale) : ''\n );\n // Each input shows its end of the range as it changes from outside.\n useEffect(() => {\n setStartText(start ? formatDate(start, resolvedFormat, locale) : '');\n }, [start, resolvedFormat, locale]);\n useEffect(() => {\n setEndText(end ? formatDate(end, resolvedFormat, locale) : '');\n }, [end, resolvedFormat, locale]);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const startRef = useRef<HTMLInputElement>(null);\n const endRef = useRef<HTMLInputElement>(null);\n const reactId = useId();\n const popoverId = id ? `${id}-popover` : `picker-${reactId}`;\n\n const { bulmaHelperClasses, rest: cleanRest } = useBulmaClasses(rest);\n\n const { shouldUseNative } = useNativeMobilePicker({\n force: mobileNative === 'auto' ? undefined : mobileNative,\n });\n const useNative = !inline && shouldUseNative;\n\n // The root borrows DateInput's container class, which places the launcher\n // and sizes a Control's icons around the field.\n const containerClass = usePrefixedClassNames(\n 'daterangeinput',\n 'dateinput-container'\n );\n const fieldClass = usePrefixedClassNames('input', 'daterangeinput-field', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-disabled': disabled,\n });\n const inputClass = usePrefixedClassNames('daterangeinput-input');\n const separatorClass = usePrefixedClassNames('daterangeinput-separator');\n const triggerClass = usePrefixedClassNames('dateinput-trigger');\n\n // What the latest request asked for, so a second request in the same event\n // sees it before React renders. The callbacks fire here rather than in a\n // state updater, which StrictMode calls twice.\n const requestedOpenRef = useRef(false);\n const setOpen = useCallback(\n (next: boolean) => {\n if (requestedOpenRef.current === next) return;\n requestedOpenRef.current = next;\n setOpenState(next);\n if (next) onOpen?.();\n else onClose?.();\n },\n [onOpen, onClose]\n );\n\n // Focus that moves inside the field, from one input to the other or from\n // the launcher, is not focus arriving, so it opens nothing. Set as the\n // focus is captured on the way in, and cleared once the input has handled\n // it, so a click that follows still opens the popover.\n const focusFromInsideRef = useRef(false);\n const handleFocusCapture = (e: React.FocusEvent<HTMLDivElement>) => {\n const from = e.relatedTarget as Node | null;\n focusFromInsideRef.current = !!from && e.currentTarget.contains(from);\n onFocusCapture?.(e);\n };\n const handleFocus = (e: React.FocusEvent<HTMLDivElement>) => {\n focusFromInsideRef.current = false;\n onFocus?.(e);\n };\n const requestOpen = useCallback(\n (next: boolean) => {\n if (next && focusFromInsideRef.current) return;\n setOpen(next);\n },\n [setOpen]\n );\n\n const commitRange = useCallback(\n (next: DateRangeValue) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n\n const constraints = useMemo(\n () => ({ shouldDisableDate, unselectableDates }),\n [shouldDisableDate, unselectableDates]\n );\n // A day the calendar disables: shouldDisableDate or unselectableDates.\n // Typing and the native inputs check the bounds alongside it.\n const isBlockedDay = useCallback(\n (d: Date) =>\n !!shouldDisableDate?.(d) ||\n !!unselectableDates?.some(u => isSameDay(u, d)),\n [shouldDisableDate, unselectableDates]\n );\n // An end the range can take: it is not disabled, and it closes a range\n // from the start, which it can't when it comes first or, unless allowed,\n // reaches over a disabled day.\n const isBlockedEnd = useCallback(\n (d: Date) =>\n isBlockedDay(d) ||\n (!!start && !canCloseRange(start, d, constraints, allowDisabledInRange)),\n [isBlockedDay, start, constraints, allowDisabledInRange]\n );\n\n // A new start keeps the end only while the two still make a range, so a\n // start moved past the end, or over a disabled day before it, clears it.\n const commitStart = useCallback(\n (next: Date | null) => {\n const keepsEnd =\n !next ||\n !end ||\n canCloseRange(next, end, constraints, allowDisabledInRange);\n commitRange([next, keepsEnd ? end : null]);\n if (next) setFocusedDate(next);\n },\n [end, constraints, allowDisabledInRange, commitRange]\n );\n // Every digit typed into the start commits, so a start passes through\n // values on its way to the one being typed. The first digits of a year make\n // a start centuries back, which can't keep the end once a disabled day may\n // lie between. Such a value waits for the segment's next digit rather than\n // clearing an end the finished start may keep.\n const startCostsEnd = useCallback(\n (d: Date) =>\n !!end && !canCloseRange(d, end, constraints, allowDisabledInRange),\n [end, constraints, allowDisabledInRange]\n );\n const commitEnd = useCallback(\n (next: Date | null) => {\n commitRange([start, next]);\n if (next) setFocusedDate(next);\n },\n [start, commitRange]\n );\n\n const handleRangeSelect = useCallback(\n (from: Date, to: Date) => {\n commitRange([from, to]);\n setFocusedDate(to);\n if (closeOnSelect) setOpen(false);\n },\n [commitRange, closeOnSelect, setOpen]\n );\n\n const tryParse = useCallback(\n (s: string): Date | null => {\n const trimmed = s.trim();\n if (!trimmed) return null;\n const fmt = typeof format === 'string' ? format : undefined;\n return parse\n ? parse(trimmed)\n : parseDate(trimmed, fmt ?? DEFAULT_DATE_FORMAT, locale);\n },\n [parse, format, locale]\n );\n\n // Typing into an empty end starts from the start, so only what differs\n // needs typing; an empty start starts from today.\n const makeEndBase = useCallback(\n () => (start ? startOfDay(start) : today()),\n [start]\n );\n\n // Where focus goes back as the popover closes: the input focused last,\n // which is the one that opened it unless the launcher did, or the start\n // input before either has had focus.\n const openerRef = useRef<HTMLInputElement | null>(null);\n const restoreFocusRef = useMemo(\n () => ({\n get current() {\n return openerRef.current ?? startRef.current;\n },\n }),\n []\n );\n\n const shared = {\n format: resolvedFormat,\n formatFn: formatDate,\n tryParse,\n locale,\n min: lowerBound,\n max,\n disabled,\n readOnly,\n editable,\n popover,\n openOnFocus,\n closeOnSelect,\n isOpen: open,\n setOpen: requestOpen,\n };\n // Each input is its own picker field. Its blur counts focus leaving it,\n // even for the other input, so text typed into one is read as focus moves\n // to the other.\n const { inputHandlers: startHandlers } = useSegmentedEntry({\n ...shared,\n value: start,\n commitValue: commitStart,\n text: startText,\n setText: setStartText,\n makeBaseDate: today,\n isBlocked: isBlockedDay,\n isUnfinishedBlocked: startCostsEnd,\n inputRef: startRef,\n containerRef: startRef,\n onFocus: () => {\n openerRef.current = startRef.current;\n },\n });\n const { inputHandlers: endHandlers } = useSegmentedEntry({\n ...shared,\n value: end,\n commitValue: commitEnd,\n text: endText,\n setText: setEndText,\n makeBaseDate: makeEndBase,\n isBlocked: isBlockedEnd,\n inputRef: endRef,\n containerRef: endRef,\n onFocus: () => {\n openerRef.current = endRef.current;\n },\n });\n\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (startRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n },\n [ref]\n );\n\n const handlePopoverClose = useCallback(() => setOpen(false), [setOpen]);\n\n const startField = startName ?? (name ? `${name}[start]` : undefined);\n const endField = endName ?? (name ? `${name}[end]` : undefined);\n const hiddenInputs = (\n <>\n {startField && (\n <input\n type=\"hidden\"\n name={startField}\n form={form}\n value={isoDay(start)}\n />\n )}\n {endField && (\n <input type=\"hidden\" name={endField} form={form} value={isoDay(end)} />\n )}\n </>\n );\n\n const separator = (\n <span className={separatorClass} aria-hidden=\"true\">\n {t.rangeSeparator}\n </span>\n );\n\n // Native mobile path: two <input type=\"date\">s, held to the same rules as\n // typing. A change the rules refuse leaves the input showing the range.\n if (useNative) {\n const nativeChange =\n (commit: (d: Date | null) => void, isBlocked: (d: Date) => boolean) =>\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // An empty value is the end cleared. A date input gives nothing else\n // that doesn't read as a date.\n const parsed = fromIsoValue(e.target.value, 'day');\n if (!parsed) commit(null);\n else if (isWithin(parsed, lowerBound, max) && !isBlocked(parsed)) {\n commit(parsed);\n }\n };\n const minIso = min ? isoDay(lowerBound) : undefined;\n const maxIso = max ? isoDay(max) : undefined;\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={onFocus}\n onFocusCapture={onFocusCapture}\n >\n <div className={fieldClass}>\n <input\n ref={combinedRef}\n type=\"date\"\n id={id}\n aria-label={t.rangeStart}\n className={inputClass}\n value={isoDay(start)}\n onChange={nativeChange(commitStart, isBlockedDay)}\n min={minIso}\n max={maxIso}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n {separator}\n <input\n ref={endRef}\n type=\"date\"\n id={id ? `${id}-end` : undefined}\n aria-label={t.rangeEnd}\n className={inputClass}\n value={isoDay(end)}\n onChange={nativeChange(commitEnd, isBlockedEnd)}\n min={start ? isoDay(start) : minIso}\n max={maxIso}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n </div>\n {hiddenInputs}\n </div>\n );\n }\n\n const calendar = (\n <Calendar\n range={range}\n onRangeSelect={handleRangeSelect}\n allowDisabledInRange={allowDisabledInRange}\n focusedDate={focusedDate}\n onFocusedDateChange={setFocusedDate}\n min={min}\n max={max}\n shouldDisableDate={shouldDisableDate}\n unselectableDates={unselectableDates}\n firstDayOfWeek={firstDayOfWeek}\n locale={locale}\n dayNames={dayNames}\n monthNames={monthNames}\n nearbyMonthDays={nearbyMonthDays}\n color={color}\n size={size}\n // The popover panel takes `popoverId`, so the calendar inside it takes\n // one of its own. Inline there is no panel.\n id={inline ? popoverId : `${popoverId}-cal`}\n autoFocusCell={open}\n labels={labels}\n />\n );\n\n if (inline) {\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={onFocus}\n onFocusCapture={onFocusCapture}\n >\n {calendar}\n {hiddenInputs}\n </div>\n );\n }\n\n const canOpen = !!popover && !disabled && !readOnly;\n const inputReadOnly = !!readOnly || !editable;\n\n // The field reads as one text box, so a press on it that misses both\n // inputs, on its padding, the gap or the separator, goes to the nearer\n // input and does what a press on that input does.\n const handleFieldMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n const startInput = startRef.current as HTMLInputElement;\n const endInput = endRef.current as HTMLInputElement;\n if (disabled || e.button !== 0) return;\n if (e.target === startInput || e.target === endInput) return;\n e.preventDefault();\n const middle =\n (startInput.getBoundingClientRect().right +\n endInput.getBoundingClientRect().left) /\n 2;\n (e.clientX < middle ? startInput : endInput).focus();\n if (openOnFocus && canOpen) requestOpen(true);\n };\n const comboboxProps = {\n type: 'text',\n role: 'combobox',\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n 'aria-controls': popoverId,\n autoComplete: 'off',\n className: inputClass,\n placeholder,\n disabled,\n readOnly: inputReadOnly,\n required,\n };\n\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={handleFocus}\n onFocusCapture={handleFocusCapture}\n >\n <div className={fieldClass} onMouseDown={handleFieldMouseDown}>\n <input\n {...comboboxProps}\n ref={combinedRef}\n id={id}\n aria-label={t.rangeStart}\n value={startText}\n {...startHandlers}\n />\n {separator}\n <input\n {...comboboxProps}\n ref={endRef}\n id={id ? `${id}-end` : undefined}\n aria-label={t.rangeEnd}\n value={endText}\n {...endHandlers}\n />\n </div>\n {popover && triggerIcon && (\n <button\n type=\"button\"\n className={triggerClass}\n // Disabled whenever the popover can't open, so a click can.\n onClick={() => setOpen(!open)}\n disabled={!canOpen}\n aria-label={t.chooseDateRange}\n aria-haspopup=\"dialog\"\n aria-controls={popoverId}\n aria-expanded={open}\n tabIndex={canOpen ? 0 : -1}\n >\n <Icon name={triggerIconName} size={size} />\n </button>\n )}\n {popover && (\n <PickerPopover\n isOpen={open}\n onClose={handlePopoverClose}\n anchorRef={containerRef}\n position={position}\n appendToBody={appendToBody}\n ariaLabel={t.chooseDateRange}\n id={popoverId}\n restoreFocusRef={restoreFocusRef}\n initialFocusSelector={CALENDAR_FOCUSED_CELL}\n >\n {calendar}\n </PickerPopover>\n )}\n {hiddenInputs}\n </div>\n );\n});\n\nDateRangeInputBase.displayName = 'DateRangeInputBase';\n\nexport default DateRangeInputBase;\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateRangeInputBase.js","sources":["../../../src/form/DateRangeInputBase.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {\n DateRangeValue,\n DayOfWeek,\n PickerLabels,\n PickerPosition,\n mergeLabels,\n} from './_pickerInternals/pickerTypes';\nimport {\n DEFAULT_DATE_FORMAT,\n DateFormatOption,\n formatDate,\n fromIsoValue,\n parseDate,\n toIsoValue,\n} from './_pickerInternals/formatters';\nimport {\n canCloseRange,\n clampDate,\n floorMin,\n isSameDay,\n isWithin,\n startOfDay,\n} from './_pickerInternals/dateUtils';\nimport { Calendar, CALENDAR_FOCUSED_CELL } from './_pickerInternals/Calendar';\nimport { PickerPopover } from './_pickerInternals/PickerPopover';\nimport { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker';\nimport { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry';\nimport { useControlLoading } from './controlLoading';\nimport { useAutoLabelledBy } from './useAutoLabelId';\nimport { Icon } from '../elements/Icon';\n\nexport type { DateRangeValue };\n\nconst EMPTY_RANGE: DateRangeValue = [null, null];\n\n/** A range's end as the form and the native inputs carry it. */\nconst isoDay = (d: Date | null): string => (d ? toIsoValue(d, 'day') : '');\n\n/** Today at local midnight, where typing into an empty end starts. */\nconst today = (): Date => startOfDay(new Date());\n\n/**\n * Props for the raw DateRangeInput base. Use the higher-level\n * `DateRangeInput` for Field/Control composition; `DateRangeInputBase` is the\n * two inputs and the popover only.\n */\nexport interface DateRangeInputBaseProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange' | 'color' | 'placeholder' | 'popover'\n >,\n Omit<BulmaClassesProps, 'color'> {\n /**\n * Controlled range, start first. Either end may be `null`, and\n * `[null, null]` is empty.\n */\n value?: DateRangeValue;\n /** Initial range for uncontrolled usage. */\n defaultValue?: DateRangeValue;\n /**\n * Fired when the range changes, with the start first. Typing commits one\n * end at a time, so a range half typed arrives as `[start, null]`. The\n * calendar commits only a finished range: its first pick marks the start\n * inside the calendar and its second commits both ends in one call. The\n * range stays ordered, so the end is never before the start.\n */\n onChange?: (range: DateRangeValue) => void;\n /** Fired when the popover opens. */\n onOpen?: () => void;\n /** Fired when the popover closes. */\n onClose?: () => void;\n /**\n * Earliest selectable date, for either end. A `min` before year 1 is raised\n * to 1 January of year 1, where the range starts without one too.\n */\n min?: Date;\n /** Latest selectable date, for either end. */\n max?: Date;\n /** Disable both inputs and the launcher. */\n disabled?: boolean;\n /** Make both inputs read-only and keep the popover closed. */\n readOnly?: boolean;\n /** Placeholder text, shown in both inputs while they are empty. */\n placeholder?: string;\n /**\n * Token format string or `Intl.DateTimeFormat` options, used by both\n * inputs.\n * @defaultValue 'YYYY-MM-DD'\n */\n format?: DateFormatOption;\n /**\n * Custom parser (use when `format` is `Intl.DateTimeFormatOptions`).\n * Enter and leaving an input call it only if the user changed its text.\n */\n parse?: (s: string) => Date | null;\n /** BCP-47 locale tag for day/month names and Intl formatting. */\n locale?: string;\n /**\n * Render the calendar inline, with no inputs and no popover. The hidden\n * form inputs still carry the range.\n */\n inline?: boolean;\n /**\n * Use two native `<input type=\"date\">`s on coarse-pointer, small-viewport\n * devices (`'auto'`), always (`true`) or never (`false`). The end input's\n * `min` follows the start, and a change goes through the same rules as\n * typing.\n */\n mobileNative?: boolean | 'auto';\n /** Allow segmented keyboard typing in both inputs. `false` makes the field picker-only. */\n editable?: boolean;\n /** Whether the calendar popover exists. `false` makes the field input-only. */\n popover?: boolean;\n /**\n * Open the popover when focus arrives in the field. Moving focus between\n * the two inputs, or back from the launcher, leaves it closed, and so does\n * the focus a closing popover hands back. A click on either input opens it.\n * With it off, the launcher or Alt+ArrowDown opens it.\n */\n openOnFocus?: boolean;\n /**\n * Close the popover once the range is picked. The first pick, which only\n * marks the start, never closes it.\n */\n closeOnSelect?: boolean;\n /** Popover anchor position relative to the field. */\n position?: PickerPosition;\n /** Render the popover into `document.body` via portal. */\n appendToBody?: boolean;\n /**\n * Bulma color modifier for the field, also carried by the calendar, where it\n * colors the range's ends and the band between them.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Render the field with rounded corners. */\n isRounded?: boolean;\n /**\n * Predicate to disable specific dates (e.g. weekends). A disabled day can\n * be neither end, typing rejects it, and a range can't include one unless\n * `allowDisabledInRange` is set.\n */\n shouldDisableDate?: (d: Date) => boolean;\n /** Convenience array of disabled dates; merged with `shouldDisableDate`. Matched by calendar day. */\n unselectableDates?: Date[];\n /**\n * Let a range include days that `shouldDisableDate` or `unselectableDates`\n * disable, such as a stay over a night with no check-ins. Its ends still\n * can't be such days. Off, a pick in the calendar past a disabled day\n * starts a new range there, typing refuses an end past one, and a start\n * typed with one before the end clears the end. Finding one walks the days\n * between, so off, a span too long to walk is refused as well.\n */\n allowDisabledInRange?: boolean;\n /** Day the week starts on (0 = Sunday). */\n firstDayOfWeek?: DayOfWeek;\n /** Override the 7 day-name labels (in calendar order, post-rotation). */\n dayNames?: string[];\n /** Override the 12 month-name labels. */\n monthNames?: string[];\n /** Show dimmed dates from adjacent months in the grid. */\n nearbyMonthDays?: boolean;\n /** Decorative left icon glyph for the wrapping `Control` (shown by default). Set `''` to hide. */\n iconLeftName?: string;\n /**\n * Show a clickable launcher button on the right that toggles the popover.\n * Hidden by default while a `Control` it sits in shows its `isLoading`\n * spinner, which shares that right edge.\n * @defaultValue true\n */\n triggerIcon?: boolean;\n /** Glyph for the right launcher button. */\n triggerIconName?: string;\n /**\n * Optional translatable string overrides. `rangeStart` and `rangeEnd` name\n * the two inputs and the range's ends in the calendar, `rangePreviewEnd`\n * describes the day a pending range would end on, `rangeSeparator` sits\n * between the inputs, and `chooseDateRange` names the launcher and the\n * popover.\n */\n labels?: PickerLabels;\n /**\n * Form field name. Two hidden inputs submit the range as `YYYY-MM-DD`,\n * named `name[start]` and `name[end]`, in every mode. The visible inputs\n * carry no name.\n */\n name?: string;\n /** Name of the hidden input carrying the start, in place of `name[start]`. */\n startName?: string;\n /** Name of the hidden input carrying the end, in place of `name[end]`. */\n endName?: string;\n /** Form id the hidden inputs belong to. */\n form?: string;\n /**\n * Mark both visible inputs required, so a form won't submit with either\n * end empty. An `inline` calendar has no visible input, so it is not\n * checked there.\n */\n required?: boolean;\n /** Id of the start input. The end input takes `${id}-end`. */\n id?: string;\n}\n\n/**\n * Raw DateRangeInput: the two inputs and the popover calendar without\n * Field/Control wrapping. Use `DateRangeInput` for the convenience wrapper.\n * Composed in a labeled `Field`, its `role=\"group\"` root points\n * `aria-labelledby` at that `Field`'s label, `inline` too, as the wrapper's\n * does, and each input keeps its own name. An `aria-label` or\n * `aria-labelledby` you give it wins over the label, and an `aria-labelledby`\n * key counts even when undefined, since it is spread over the group's own.\n *\n * @function\n * @param {DateRangeInputBaseProps} props\n * @returns {JSX.Element}\n */\nexport const DateRangeInputBase = forwardRef<\n HTMLInputElement,\n DateRangeInputBaseProps\n>((props, ref) => {\n const {\n value: controlledValue,\n defaultValue,\n onChange,\n onOpen,\n onClose,\n min,\n max,\n disabled,\n readOnly,\n placeholder,\n format,\n parse,\n locale,\n inline = false,\n mobileNative = 'auto',\n editable = true,\n popover = true,\n openOnFocus = true,\n closeOnSelect = true,\n position = 'bottom-left',\n appendToBody = false,\n color,\n size,\n isRounded,\n shouldDisableDate,\n unselectableDates,\n allowDisabledInRange = false,\n firstDayOfWeek = 0,\n dayNames,\n monthNames,\n nearbyMonthDays = true,\n iconLeftName: _iconLeftName,\n triggerIcon: triggerIconProp,\n triggerIconName = 'chevron-down',\n labels,\n name,\n startName,\n endName,\n form,\n required,\n id,\n className,\n onFocus,\n onFocusCapture,\n ...rest\n } = props;\n // The launcher gives way to the loading spinner of a Control this sits in.\n const controlLoading = useControlLoading();\n const triggerIcon = triggerIconProp ?? !controlLoading;\n\n const t = mergeLabels(labels);\n const resolvedFormat = format ?? DEFAULT_DATE_FORMAT;\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<DateRangeValue>(\n defaultValue ?? EMPTY_RANGE\n );\n const range = isControlled ? controlledValue : internalValue;\n const [start, end] = range;\n\n // Nothing before year 1 is in range, as in HTML's date inputs.\n const lowerBound = useMemo(() => floorMin(min), [min]);\n\n const [focusedDate, setFocusedDate] = useState<Date>(() =>\n clampDate(start ?? end ?? new Date(), lowerBound, max)\n );\n // Re-clamp the focused day if the bounds change after mount, so the\n // calendar never shows a month outside them.\n useEffect(() => {\n setFocusedDate(prev => clampDate(prev, lowerBound, max));\n }, [lowerBound, max]);\n\n const [open, setOpenState] = useState(false);\n const [startText, setStartText] = useState(() =>\n start ? formatDate(start, resolvedFormat, locale) : ''\n );\n const [endText, setEndText] = useState(() =>\n end ? formatDate(end, resolvedFormat, locale) : ''\n );\n // Each input shows its end of the range as it changes from outside.\n useEffect(() => {\n setStartText(start ? formatDate(start, resolvedFormat, locale) : '');\n }, [start, resolvedFormat, locale]);\n useEffect(() => {\n setEndText(end ? formatDate(end, resolvedFormat, locale) : '');\n }, [end, resolvedFormat, locale]);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const startRef = useRef<HTMLInputElement>(null);\n const endRef = useRef<HTMLInputElement>(null);\n const reactId = useId();\n const popoverId = id ? `${id}-popover` : `picker-${reactId}`;\n\n const { bulmaHelperClasses, rest: cleanRest } = useBulmaClasses(rest);\n // Two inputs can't share a labeled Field's `for`, so inside one the group\n // points `aria-labelledby` at that Field's label, as `DateRangeInput`\n // does, in every mode. A name the caller gave the group wins, and so does\n // the `aria-labelledby` that wrapper always passes, so it decides there.\n const { ariaLabelledBy } = useAutoLabelledBy({\n label: undefined,\n rendersLabel: false,\n callerProps: rest,\n });\n\n const { shouldUseNative } = useNativeMobilePicker({\n force: mobileNative === 'auto' ? undefined : mobileNative,\n });\n const useNative = !inline && shouldUseNative;\n\n // The root borrows DateInput's container class, which places the launcher\n // and sizes a Control's icons around the field.\n const containerClass = usePrefixedClassNames(\n 'daterangeinput',\n 'dateinput-container'\n );\n const fieldClass = usePrefixedClassNames('input', 'daterangeinput-field', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-disabled': disabled,\n });\n const inputClass = usePrefixedClassNames('daterangeinput-input');\n const separatorClass = usePrefixedClassNames('daterangeinput-separator');\n const triggerClass = usePrefixedClassNames('dateinput-trigger');\n\n // What the latest request asked for, so a second request in the same event\n // sees it before React renders. The callbacks fire here rather than in a\n // state updater, which StrictMode calls twice.\n const requestedOpenRef = useRef(false);\n const setOpen = useCallback(\n (next: boolean) => {\n if (requestedOpenRef.current === next) return;\n requestedOpenRef.current = next;\n setOpenState(next);\n if (next) onOpen?.();\n else onClose?.();\n },\n [onOpen, onClose]\n );\n\n // Focus that moves inside the field, from one input to the other or from\n // the launcher, is not focus arriving, so it opens nothing. Set as the\n // focus is captured on the way in, and cleared once the input has handled\n // it, so a click that follows still opens the popover.\n const focusFromInsideRef = useRef(false);\n const handleFocusCapture = (e: React.FocusEvent<HTMLDivElement>) => {\n const from = e.relatedTarget as Node | null;\n focusFromInsideRef.current = !!from && e.currentTarget.contains(from);\n onFocusCapture?.(e);\n };\n const handleFocus = (e: React.FocusEvent<HTMLDivElement>) => {\n focusFromInsideRef.current = false;\n onFocus?.(e);\n };\n const requestOpen = useCallback(\n (next: boolean) => {\n if (next && focusFromInsideRef.current) return;\n setOpen(next);\n },\n [setOpen]\n );\n\n const commitRange = useCallback(\n (next: DateRangeValue) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n\n const constraints = useMemo(\n () => ({ shouldDisableDate, unselectableDates }),\n [shouldDisableDate, unselectableDates]\n );\n // A day the calendar disables: shouldDisableDate or unselectableDates.\n // Typing and the native inputs check the bounds alongside it.\n const isBlockedDay = useCallback(\n (d: Date) =>\n !!shouldDisableDate?.(d) ||\n !!unselectableDates?.some(u => isSameDay(u, d)),\n [shouldDisableDate, unselectableDates]\n );\n // An end the range can take: it is not disabled, and it closes a range\n // from the start, which it can't when it comes first or, unless allowed,\n // reaches over a disabled day.\n const isBlockedEnd = useCallback(\n (d: Date) =>\n isBlockedDay(d) ||\n (!!start && !canCloseRange(start, d, constraints, allowDisabledInRange)),\n [isBlockedDay, start, constraints, allowDisabledInRange]\n );\n\n // A new start keeps the end only while the two still make a range, so a\n // start moved past the end, or over a disabled day before it, clears it.\n const commitStart = useCallback(\n (next: Date | null) => {\n const keepsEnd =\n !next ||\n !end ||\n canCloseRange(next, end, constraints, allowDisabledInRange);\n commitRange([next, keepsEnd ? end : null]);\n if (next) setFocusedDate(next);\n },\n [end, constraints, allowDisabledInRange, commitRange]\n );\n // Every digit typed into the start commits, so a start passes through\n // values on its way to the one being typed. The first digits of a year make\n // a start centuries back, which can't keep the end once a disabled day may\n // lie between. Such a value waits for the segment's next digit rather than\n // clearing an end the finished start may keep.\n const startCostsEnd = useCallback(\n (d: Date) =>\n !!end && !canCloseRange(d, end, constraints, allowDisabledInRange),\n [end, constraints, allowDisabledInRange]\n );\n const commitEnd = useCallback(\n (next: Date | null) => {\n commitRange([start, next]);\n if (next) setFocusedDate(next);\n },\n [start, commitRange]\n );\n\n const handleRangeSelect = useCallback(\n (from: Date, to: Date) => {\n commitRange([from, to]);\n setFocusedDate(to);\n if (closeOnSelect) setOpen(false);\n },\n [commitRange, closeOnSelect, setOpen]\n );\n\n const tryParse = useCallback(\n (s: string): Date | null => {\n const trimmed = s.trim();\n if (!trimmed) return null;\n const fmt = typeof format === 'string' ? format : undefined;\n return parse\n ? parse(trimmed)\n : parseDate(trimmed, fmt ?? DEFAULT_DATE_FORMAT, locale);\n },\n [parse, format, locale]\n );\n\n // Typing into an empty end starts from the start, so only what differs\n // needs typing; an empty start starts from today.\n const makeEndBase = useCallback(\n () => (start ? startOfDay(start) : today()),\n [start]\n );\n\n // Where focus goes back as the popover closes: the input focused last,\n // which is the one that opened it unless the launcher did, or the start\n // input before either has had focus.\n const openerRef = useRef<HTMLInputElement | null>(null);\n const restoreFocusRef = useMemo(\n () => ({\n get current() {\n return openerRef.current ?? startRef.current;\n },\n }),\n []\n );\n\n const shared = {\n format: resolvedFormat,\n formatFn: formatDate,\n tryParse,\n locale,\n min: lowerBound,\n max,\n disabled,\n readOnly,\n editable,\n popover,\n openOnFocus,\n closeOnSelect,\n isOpen: open,\n setOpen: requestOpen,\n };\n // Each input is its own picker field. Its blur counts focus leaving it,\n // even for the other input, so text typed into one is read as focus moves\n // to the other.\n const { inputHandlers: startHandlers } = useSegmentedEntry({\n ...shared,\n value: start,\n commitValue: commitStart,\n text: startText,\n setText: setStartText,\n makeBaseDate: today,\n isBlocked: isBlockedDay,\n isUnfinishedBlocked: startCostsEnd,\n inputRef: startRef,\n containerRef: startRef,\n onFocus: () => {\n openerRef.current = startRef.current;\n },\n });\n const { inputHandlers: endHandlers } = useSegmentedEntry({\n ...shared,\n value: end,\n commitValue: commitEnd,\n text: endText,\n setText: setEndText,\n makeBaseDate: makeEndBase,\n isBlocked: isBlockedEnd,\n inputRef: endRef,\n containerRef: endRef,\n onFocus: () => {\n openerRef.current = endRef.current;\n },\n });\n\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (startRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n },\n [ref]\n );\n\n const handlePopoverClose = useCallback(() => setOpen(false), [setOpen]);\n\n const startField = startName ?? (name ? `${name}[start]` : undefined);\n const endField = endName ?? (name ? `${name}[end]` : undefined);\n const hiddenInputs = (\n <>\n {startField && (\n <input\n type=\"hidden\"\n name={startField}\n form={form}\n value={isoDay(start)}\n />\n )}\n {endField && (\n <input type=\"hidden\" name={endField} form={form} value={isoDay(end)} />\n )}\n </>\n );\n\n const separator = (\n <span className={separatorClass} aria-hidden=\"true\">\n {t.rangeSeparator}\n </span>\n );\n\n // Native mobile path: two <input type=\"date\">s, held to the same rules as\n // typing. A change the rules refuse leaves the input showing the range.\n if (useNative) {\n const nativeChange =\n (commit: (d: Date | null) => void, isBlocked: (d: Date) => boolean) =>\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // An empty value is the end cleared. A date input gives nothing else\n // that doesn't read as a date.\n const parsed = fromIsoValue(e.target.value, 'day');\n if (!parsed) commit(null);\n else if (isWithin(parsed, lowerBound, max) && !isBlocked(parsed)) {\n commit(parsed);\n }\n };\n const minIso = min ? isoDay(lowerBound) : undefined;\n const maxIso = max ? isoDay(max) : undefined;\n return (\n <div\n aria-labelledby={ariaLabelledBy}\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={onFocus}\n onFocusCapture={onFocusCapture}\n >\n <div className={fieldClass}>\n <input\n ref={combinedRef}\n type=\"date\"\n id={id}\n aria-label={t.rangeStart}\n className={inputClass}\n value={isoDay(start)}\n onChange={nativeChange(commitStart, isBlockedDay)}\n min={minIso}\n max={maxIso}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n {separator}\n <input\n ref={endRef}\n type=\"date\"\n id={id ? `${id}-end` : undefined}\n aria-label={t.rangeEnd}\n className={inputClass}\n value={isoDay(end)}\n onChange={nativeChange(commitEnd, isBlockedEnd)}\n min={start ? isoDay(start) : minIso}\n max={maxIso}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n </div>\n {hiddenInputs}\n </div>\n );\n }\n\n const calendar = (\n <Calendar\n range={range}\n onRangeSelect={handleRangeSelect}\n allowDisabledInRange={allowDisabledInRange}\n focusedDate={focusedDate}\n onFocusedDateChange={setFocusedDate}\n min={min}\n max={max}\n shouldDisableDate={shouldDisableDate}\n unselectableDates={unselectableDates}\n firstDayOfWeek={firstDayOfWeek}\n locale={locale}\n dayNames={dayNames}\n monthNames={monthNames}\n nearbyMonthDays={nearbyMonthDays}\n color={color}\n size={size}\n // The popover panel takes `popoverId`, so the calendar inside it takes\n // one of its own. Inline there is no panel.\n id={inline ? popoverId : `${popoverId}-cal`}\n autoFocusCell={open}\n labels={labels}\n />\n );\n\n if (inline) {\n return (\n <div\n aria-labelledby={ariaLabelledBy}\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={onFocus}\n onFocusCapture={onFocusCapture}\n >\n {calendar}\n {hiddenInputs}\n </div>\n );\n }\n\n const canOpen = !!popover && !disabled && !readOnly;\n const inputReadOnly = !!readOnly || !editable;\n\n // The field reads as one text box, so a press on it that misses both\n // inputs, on its padding, the gap or the separator, goes to the nearer\n // input and does what a press on that input does.\n const handleFieldMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n const startInput = startRef.current as HTMLInputElement;\n const endInput = endRef.current as HTMLInputElement;\n if (disabled || e.button !== 0) return;\n if (e.target === startInput || e.target === endInput) return;\n e.preventDefault();\n const middle =\n (startInput.getBoundingClientRect().right +\n endInput.getBoundingClientRect().left) /\n 2;\n (e.clientX < middle ? startInput : endInput).focus();\n if (openOnFocus && canOpen) requestOpen(true);\n };\n const comboboxProps = {\n type: 'text',\n role: 'combobox',\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n 'aria-controls': popoverId,\n autoComplete: 'off',\n className: inputClass,\n placeholder,\n disabled,\n readOnly: inputReadOnly,\n required,\n };\n\n return (\n <div\n aria-labelledby={ariaLabelledBy}\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={handleFocus}\n onFocusCapture={handleFocusCapture}\n >\n <div className={fieldClass} onMouseDown={handleFieldMouseDown}>\n <input\n {...comboboxProps}\n ref={combinedRef}\n id={id}\n aria-label={t.rangeStart}\n value={startText}\n {...startHandlers}\n />\n {separator}\n <input\n {...comboboxProps}\n ref={endRef}\n id={id ? `${id}-end` : undefined}\n aria-label={t.rangeEnd}\n value={endText}\n {...endHandlers}\n />\n </div>\n {popover && triggerIcon && (\n <button\n type=\"button\"\n className={triggerClass}\n // Disabled whenever the popover can't open, so a click can.\n onClick={() => setOpen(!open)}\n disabled={!canOpen}\n aria-label={t.chooseDateRange}\n aria-haspopup=\"dialog\"\n aria-controls={popoverId}\n aria-expanded={open}\n tabIndex={canOpen ? 0 : -1}\n >\n <Icon name={triggerIconName} size={size} />\n </button>\n )}\n {popover && (\n <PickerPopover\n isOpen={open}\n onClose={handlePopoverClose}\n anchorRef={containerRef}\n position={position}\n appendToBody={appendToBody}\n ariaLabel={t.chooseDateRange}\n id={popoverId}\n restoreFocusRef={restoreFocusRef}\n initialFocusSelector={CALENDAR_FOCUSED_CELL}\n >\n {calendar}\n </PickerPopover>\n )}\n {hiddenInputs}\n </div>\n );\n});\n\nDateRangeInputBase.displayName = 'DateRangeInputBase';\n\nexport default DateRangeInputBase;\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
package/dist/esm/form/Field.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import React, { useId } from 'react';
|
|
3
|
+
import React, { useId, useMemo } from 'react';
|
|
4
4
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
5
5
|
import { withSubComponents } from '../helpers/withSubComponents.js';
|
|
6
6
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
@@ -13,7 +13,12 @@ import { Control } from './Control.js';
|
|
|
13
13
|
* not a `<label>`, so text placed straight in it names nothing. Put a `<label>`
|
|
14
14
|
* with the `label` class inside it and point its `htmlFor` at the control's
|
|
15
15
|
* `id`, or give the horizontal `Field` a `label` prop, which renders this
|
|
16
|
-
* column and its `<label>` for you.
|
|
16
|
+
* column and its `<label>` for you. A `<label>` you put here names the
|
|
17
|
+
* control through its `htmlFor` alone: a range `Slider`'s thumbs and an
|
|
18
|
+
* `Autocomplete`'s suggestion list point `aria-labelledby` at a `Field`'s
|
|
19
|
+
* label only when its `label` prop renders it and it names the control.
|
|
20
|
+
* Where it would not name the control on its own, as in an inner `Field`,
|
|
21
|
+
* pass `labelProps={{ htmlFor, id }}` with a matching `id` on the control.
|
|
17
22
|
*
|
|
18
23
|
* @function
|
|
19
24
|
* @param {FieldLabelProps} props - Props for the FieldLabel component.
|
|
@@ -117,20 +122,25 @@ const FieldComponent = ({ horizontal, grouped, hasAddons, narrow, label, labelSi
|
|
|
117
122
|
const targetId = label && !userWiredLabel && !grouped && !hasAddons
|
|
118
123
|
? generatedId
|
|
119
124
|
: undefined;
|
|
120
|
-
// A group control (Radios, Checkboxes, Rate, DateRangeInput
|
|
121
|
-
// that `for`, so it points `aria-labelledby` at the label
|
|
125
|
+
// A group control (Radios, Checkboxes, Rate, DateRangeInput and its base)
|
|
126
|
+
// cannot take that `for`, so it points `aria-labelledby` at the label
|
|
127
|
+
// itself (#939).
|
|
122
128
|
// The label gets an id whenever the association is on, unless the caller
|
|
123
129
|
// gave it one.
|
|
124
130
|
const labelId = labelProps?.id ?? (targetId ? `${targetId}-label` : undefined);
|
|
125
|
-
// What the rendered label's `for` points at, generated or the caller's,
|
|
126
|
-
// a control can tell when a label wired by hand
|
|
127
|
-
// Field passes on its
|
|
131
|
+
// What the rendered label's `for` points at, generated or the caller's, and
|
|
132
|
+
// the id it renders with, so a control can tell when a label wired by hand
|
|
133
|
+
// names it and point at that label. An unlabeled Field passes on its
|
|
134
|
+
// parent's. Unlike `targetId`, a label wired by hand passes on its own in
|
|
135
|
+
// `grouped`/`hasAddons` Fields too, on purpose: those only stop the Field
|
|
136
|
+
// picking one control out of several, and the caller's `for` has picked
|
|
137
|
+
// one, so a range Slider or Autocomplete it names points at that label in
|
|
138
|
+
// a row as well. A group reads the label element id below instead, which
|
|
139
|
+
// stays off for a label wired by hand, since no group takes its `for`.
|
|
128
140
|
const inheritedLabelFor = useFieldLabelFor();
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
: targetId
|
|
133
|
-
: inheritedLabelFor;
|
|
141
|
+
const labelForTarget = userWiredLabel ? labelProps.htmlFor : targetId;
|
|
142
|
+
const ownLabelFor = useMemo(() => ({ htmlFor: labelForTarget, id: labelId }), [labelForTarget, labelId]);
|
|
143
|
+
const labelFor = label ? ownLabelFor : inheritedLabelFor;
|
|
134
144
|
let renderedLabel = null;
|
|
135
145
|
if (label) {
|
|
136
146
|
if (horizontal) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.js","sources":["../../../src/form/Field.tsx"],"sourcesContent":["import React, { useId } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport {\n FieldProvider,\n FieldLabelIdProvider,\n FieldLabelElementIdProvider,\n FieldLabelForProvider,\n useFieldLabelFor,\n} from './FormContext';\nimport { Control } from './Control';\n\n/**\n * Props for the Field component.\n */\nexport interface FieldProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Renders the field as horizontal (label and control side by side). */\n horizontal?: boolean;\n /** Group controls in a row (optionally centered, right, or multiline). */\n grouped?: boolean | 'centered' | 'right' | 'multiline';\n /** Group controls as addons (optionally centered or right-aligned). */\n hasAddons?: boolean | 'centered' | 'right';\n /** Constrains the field to its content's width (used inside horizontal field bodies). */\n narrow?: boolean;\n /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children. Only the single inputs take the `htmlFor`, so with a group or any other content it matches nothing. Pass `labelProps={{ htmlFor }}` to wire your own `id`, or `labelProps={{ htmlFor: undefined }}` to opt out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */\n label?: React.ReactNode;\n /** Size for the label. */\n labelSize?: 'small' | 'normal' | 'medium' | 'large';\n /** Props for the label element. An explicit `htmlFor` key — even set to `undefined` — takes over the association. An `id` here is the one a group control's, or a range `Slider`'s, `aria-labelledby` points at; otherwise the label gets a generated one while the association is on. To point a group in an inner `Field` at this label by hand, pass that `id` with `htmlFor: undefined`, or the label keeps a generated `htmlFor` that nothing takes. */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Text color for the field. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma color for the field. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color for the field. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Field content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the FieldLabel component.\n */\nexport interface FieldLabelProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Size for the field label. */\n size?: 'small' | 'normal' | 'medium' | 'large';\n /** Text color for the label. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma color for the label. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color for the label. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Field label content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the FieldBody component.\n */\nexport interface FieldBodyProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Text color for the field body. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma color for the field body. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color for the field body. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Field body content. */\n children?: React.ReactNode;\n}\n\n/**\n * FieldLabel component for rendering a Bulma field label. It renders the\n * label column of a horizontal `Field` (a `div` with the `field-label` class),\n * not a `<label>`, so text placed straight in it names nothing. Put a `<label>`\n * with the `label` class inside it and point its `htmlFor` at the control's\n * `id`, or give the horizontal `Field` a `label` prop, which renders this\n * column and its `<label>` for you.\n *\n * @function\n * @param {FieldLabelProps} props - Props for the FieldLabel component.\n * @returns {JSX.Element} The rendered field label.\n *\n * @example\n * <FieldLabel size=\"normal\">\n * <label className=\"label\" htmlFor=\"name\">Name</label>\n * </FieldLabel>\n */\nexport const FieldLabel: React.FC<FieldLabelProps> = ({\n size,\n textColor,\n bgColor,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('field-label', {\n [`is-${size}`]: !!size,\n });\n const fieldLabelClass = classNames(mainClass, bulmaHelperClasses, className);\n // Spread ...props and ...rest so custom props like data-testid are included\n return (\n <div className={fieldLabelClass} {...props} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * FieldBody component for rendering Bulma field body.\n *\n * @function\n * @param {FieldBodyProps} props - Props for the FieldBody component.\n * @returns {JSX.Element} The rendered field body.\n *\n * @example\n * <FieldBody><input className=\"input\" /></FieldBody>\n */\nexport const FieldBody: React.FC<FieldBodyProps> = ({\n textColor,\n bgColor,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('field-body');\n const fieldBodyClass = classNames(mainClass, bulmaHelperClasses, className);\n // Spread ...props and ...rest so custom props like data-testid are included\n return (\n <div className={fieldBodyClass} {...props} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * The `Field` component is a Bulma-styled form field container.\n *\n * @function\n * @param {FieldProps} props - Props for the Field component.\n * @returns {JSX.Element} The rendered field container.\n * @see {@link https://bulma.io/documentation/form/general/#field | Bulma Field documentation}\n *\n * @example\n * // Labelled field — the label auto-associates with the composed base\n * <Field label=\"Email\">\n * <Control>\n * <InputBase type=\"email\" />\n * </Control>\n * </Field>\n *\n * @example\n * // Horizontal field\n * <Field horizontal label=\"Name\">\n * <Control>\n * <InputBase />\n * </Control>\n * </Field>\n */\nconst FieldComponent: React.FC<FieldProps> = ({\n horizontal,\n grouped,\n hasAddons,\n narrow,\n label,\n labelSize,\n labelProps,\n textColor,\n color: _fieldColor,\n bgColor,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('field', {\n 'is-horizontal': horizontal,\n 'has-addons': !!hasAddons,\n 'has-addons-centered': hasAddons === 'centered',\n 'has-addons-right': hasAddons === 'right',\n 'is-narrow': narrow,\n 'is-grouped':\n grouped === true ||\n grouped === 'centered' ||\n grouped === 'right' ||\n grouped === 'multiline',\n 'is-grouped-centered': grouped === 'centered',\n 'is-grouped-right': grouped === 'right',\n 'is-grouped-multiline': grouped === 'multiline',\n });\n const fieldClass = classNames(mainClass, bulmaHelperClasses, className);\n\n // Default labelSize to 'normal' when horizontal for proper baseline alignment\n const effectiveLabelSize = labelSize ?? (horizontal ? 'normal' : undefined);\n\n const labelClass = usePrefixedClassNames('label');\n\n // Auto-associate the label with a single composed base control (#495): the\n // label points at a generated id shared via context, which a composed base\n // adopts when the user supplied no id of their own.\n // Presence semantics on htmlFor — even an explicit `htmlFor: undefined`\n // means the caller owns the association. Grouped/addons fields hold several\n // controls, so no single association is generated for them.\n const generatedId = useId();\n const userWiredLabel = !!labelProps && 'htmlFor' in labelProps;\n const targetId =\n label && !userWiredLabel && !grouped && !hasAddons\n ? generatedId\n : undefined;\n // A group control (Radios, Checkboxes, Rate, DateRangeInput) cannot take\n // that `for`, so it points `aria-labelledby` at the label itself (#939).\n // The label gets an id whenever the association is on, unless the caller\n // gave it one.\n const labelId =\n labelProps?.id ?? (targetId ? `${targetId}-label` : undefined);\n // What the rendered label's `for` points at, generated or the caller's, so\n // a control can tell when a label wired by hand names it. An unlabeled\n // Field passes on its parent's.\n const inheritedLabelFor = useFieldLabelFor();\n const labelFor = label\n ? userWiredLabel\n ? labelProps.htmlFor\n : targetId\n : inheritedLabelFor;\n\n let renderedLabel = null;\n if (label) {\n if (horizontal) {\n renderedLabel = (\n <FieldLabel size={effectiveLabelSize}>\n <label\n htmlFor={targetId}\n {...labelProps}\n id={labelId}\n className={classNames(labelClass, labelProps?.className)}\n style={labelProps?.style}\n >\n {label}\n </label>\n </FieldLabel>\n );\n } else {\n renderedLabel = (\n <label\n htmlFor={targetId}\n {...labelProps}\n id={labelId}\n className={classNames(labelClass, labelProps?.className)}\n style={{ display: 'block', ...(labelProps?.style || {}) }}\n >\n {label}\n </label>\n );\n }\n }\n\n // If horizontal, wrap children in FieldBody (unless the user already provided\n // a FieldBody — either as the single child, or as one element among siblings\n // like <Field.Label/> + <Field.Body/>).\n let content = children;\n if (horizontal) {\n const isFieldBody = (c: React.ReactNode): boolean =>\n React.isValidElement(c) &&\n // @ts-expect-error displayName isn't on the public type\n (c.type === FieldBody || c.type?.displayName === 'FieldBody');\n const isFieldLabel = (c: React.ReactNode): boolean =>\n React.isValidElement(c) &&\n // @ts-expect-error displayName isn't on the public type\n (c.type === FieldLabel || c.type?.displayName === 'FieldLabel');\n const childArray = React.Children.toArray(children);\n const userProvidedStructure = childArray.some(\n c => isFieldBody(c) || isFieldLabel(c)\n );\n if (userProvidedStructure) {\n content = children;\n } else {\n content = <FieldBody>{children}</FieldBody>;\n }\n }\n\n return (\n <FieldProvider value={true}>\n <FieldLabelIdProvider value={targetId}>\n <FieldLabelElementIdProvider value={targetId ? labelId : undefined}>\n <FieldLabelForProvider value={labelFor}>\n <div className={fieldClass} {...rest}>\n {renderedLabel}\n {content}\n </div>\n </FieldLabelForProvider>\n </FieldLabelElementIdProvider>\n </FieldLabelIdProvider>\n </FieldProvider>\n );\n};\n\nFieldLabel.displayName = 'FieldLabel';\nFieldBody.displayName = 'FieldBody';\n\nexport const Field = withSubComponents(\n FieldComponent,\n {\n Label: FieldLabel,\n Body: FieldBody,\n Control,\n },\n 'Field'\n);\n\nexport default Field;\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;AA4FA;;;;;;;;;;;;;;;;AAgBG;MACU,UAAU,GAA8B,CAAC,EACpD,IAAI,EACJ,SAAS,EACT,OAAO,EACP,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AACnD,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,eAAe,EAAE,OAAO;AACxB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;AAEF,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,aAAa,EAAE;AACrD,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACvB,KAAA,CAAC;IACF,MAAM,eAAe,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;;AAE5E,IAAA,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,eAAe,EAAA,GAAM,KAAK,EAAA,GAAM,IAAI,EAAA,QAAA,EACjD,QAAQ,EAAA,CACL;AAEV;AAEA;;;;;;;;;AASG;AACI,MAAM,SAAS,GAA6B,CAAC,EAClD,SAAS,EACT,OAAO,EACP,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AACnD,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,eAAe,EAAE,OAAO;AACxB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;AAEF,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,YAAY,CAAC;IACrD,MAAM,cAAc,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;;AAE3E,IAAA,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,cAAc,EAAA,GAAM,KAAK,EAAA,GAAM,IAAI,EAAA,QAAA,EAChD,QAAQ,EAAA,CACL;AAEV;AAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBG;AACH,MAAM,cAAc,GAAyB,CAAC,EAC5C,UAAU,EACV,OAAO,EACP,SAAS,EACT,MAAM,EACN,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,KAAK,EAAE,WAAW,EAClB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AACnD,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,eAAe,EAAE,OAAO;AACxB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;AAEF,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE;AAC/C,QAAA,eAAe,EAAE,UAAU;QAC3B,YAAY,EAAE,CAAC,CAAC,SAAS;QACzB,qBAAqB,EAAE,SAAS,KAAK,UAAU;QAC/C,kBAAkB,EAAE,SAAS,KAAK,OAAO;AACzC,QAAA,WAAW,EAAE,MAAM;QACnB,YAAY,EACV,OAAO,KAAK,IAAI;AAChB,YAAA,OAAO,KAAK,UAAU;AACtB,YAAA,OAAO,KAAK,OAAO;AACnB,YAAA,OAAO,KAAK,WAAW;QACzB,qBAAqB,EAAE,OAAO,KAAK,UAAU;QAC7C,kBAAkB,EAAE,OAAO,KAAK,OAAO;QACvC,sBAAsB,EAAE,OAAO,KAAK,WAAW;AAChD,KAAA,CAAC;IACF,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;;AAGvE,IAAA,MAAM,kBAAkB,GAAG,SAAS,KAAK,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3E,IAAA,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC;;;;;;;AAQjD,IAAA,MAAM,WAAW,GAAG,KAAK,EAAE;IAC3B,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,IAAI,SAAS,IAAI,UAAU;IAC9D,MAAM,QAAQ,GACZ,KAAK,IAAI,CAAC,cAAc,IAAI,CAAC,OAAO,IAAI,CAAC;AACvC,UAAE;UACA,SAAS;;;;;AAKf,IAAA,MAAM,OAAO,GACX,UAAU,EAAE,EAAE,KAAK,QAAQ,GAAG,CAAA,EAAG,QAAQ,CAAA,MAAA,CAAQ,GAAG,SAAS,CAAC;;;;AAIhE,IAAA,MAAM,iBAAiB,GAAG,gBAAgB,EAAE;IAC5C,MAAM,QAAQ,GAAG;AACf,UAAE;cACE,UAAU,CAAC;AACb,cAAE;UACF,iBAAiB;IAErB,IAAI,aAAa,GAAG,IAAI;IACxB,IAAI,KAAK,EAAE;QACT,IAAI,UAAU,EAAE;AACd,YAAA,aAAa,IACXA,GAAA,CAAC,UAAU,EAAA,EAAC,IAAI,EAAE,kBAAkB,EAAA,QAAA,EAClCA,GAAA,CAAA,OAAA,EAAA,EACE,OAAO,EAAE,QAAQ,EAAA,GACb,UAAU,EACd,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EACxD,KAAK,EAAE,UAAU,EAAE,KAAK,EAAA,QAAA,EAEvB,KAAK,EAAA,CACA,EAAA,CACG,CACd;QACH;aAAO;YACL,aAAa,IACXA,GAAA,CAAA,OAAA,EAAA,EACE,OAAO,EAAE,QAAQ,EAAA,GACb,UAAU,EACd,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EACxD,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,YAExD,KAAK,EAAA,CACA,CACT;QACH;IACF;;;;IAKA,IAAI,OAAO,GAAG,QAAQ;IACtB,IAAI,UAAU,EAAE;AACd,QAAA,MAAM,WAAW,GAAG,CAAC,CAAkB,KACrC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;;AAEvB,aAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,WAAW,CAAC;AAC/D,QAAA,MAAM,YAAY,GAAG,CAAC,CAAkB,KACtC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;;AAEvB,aAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,YAAY,CAAC;QACjE,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;QACnD,MAAM,qBAAqB,GAAG,UAAU,CAAC,IAAI,CAC3C,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,CACvC;QACD,IAAI,qBAAqB,EAAE;YACzB,OAAO,GAAG,QAAQ;QACpB;aAAO;AACL,YAAA,OAAO,GAAGA,GAAA,CAAC,SAAS,EAAA,EAAA,QAAA,EAAE,QAAQ,GAAa;QAC7C;IACF;IAEA,QACEA,GAAA,CAAC,aAAa,EAAA,EAAC,KAAK,EAAE,IAAI,EAAA,QAAA,EACxBA,GAAA,CAAC,oBAAoB,EAAA,EAAC,KAAK,EAAE,QAAQ,EAAA,QAAA,EACnCA,GAAA,CAAC,2BAA2B,EAAA,EAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,EAAA,QAAA,EAChEA,GAAA,CAAC,qBAAqB,EAAA,EAAC,KAAK,EAAE,QAAQ,EAAA,QAAA,EACpCC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,EAAA,GAAM,IAAI,EAAA,QAAA,EAAA,CACjC,aAAa,EACb,OAAO,CAAA,EAAA,CACJ,EAAA,CACgB,EAAA,CACI,EAAA,CACT,EAAA,CACT;AAEpB,CAAC;AAED,UAAU,CAAC,WAAW,GAAG,YAAY;AACrC,SAAS,CAAC,WAAW,GAAG,WAAW;AAE5B,MAAM,KAAK,GAAG,iBAAiB,CACpC,cAAc,EACd;AACE,IAAA,KAAK,EAAE,UAAU;AACjB,IAAA,IAAI,EAAE,SAAS;IACf,OAAO;CACR,EACD,OAAO;;"}
|
|
1
|
+
{"version":3,"file":"Field.js","sources":["../../../src/form/Field.tsx"],"sourcesContent":["import React, { useId, useMemo } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport {\n FieldProvider,\n FieldLabelIdProvider,\n FieldLabelElementIdProvider,\n FieldLabelForProvider,\n useFieldLabelFor,\n} from './FormContext';\nimport { Control } from './Control';\n\n/**\n * Props for the Field component.\n */\nexport interface FieldProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Renders the field as horizontal (label and control side by side). */\n horizontal?: boolean;\n /** Group controls in a row (optionally centered, right, or multiline). */\n grouped?: boolean | 'centered' | 'right' | 'multiline';\n /** Group controls as addons (optionally centered or right-aligned). */\n hasAddons?: boolean | 'centered' | 'right';\n /** Constrains the field to its content's width (used inside horizontal field bodies). */\n narrow?: boolean;\n /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete` also names its open suggestion list after the label through `aria-labelledby`. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children. Only the single inputs take the `htmlFor`, so with a group or any other content it matches nothing. Pass `labelProps={{ htmlFor }}` to wire your own `id`, or `labelProps={{ htmlFor: undefined }}` to opt out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */\n label?: React.ReactNode;\n /** Size for the label. */\n labelSize?: 'small' | 'normal' | 'medium' | 'large';\n /** Props for the label element. An explicit `htmlFor` key — even set to `undefined` — takes over the association. While the association is on, the label renders with the `id` given here, or a generated one, and a group control, a range `Slider`'s thumbs and an `Autocomplete`'s suggestion list point `aria-labelledby` at it. A label you take over gets no generated id, and no group points at it on its own. With an `id` here, though, a range `Slider` or an `Autocomplete` whose `id` your `htmlFor` names still points its thumbs or its suggestion list at it, in a `grouped` or `hasAddons` Field too. To point a group in an inner `Field` at this label by hand, pass that `id` with `htmlFor: undefined`, or the label keeps a generated `htmlFor` that nothing takes. */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Text color for the field. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma color for the field. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color for the field. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Field content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the FieldLabel component.\n */\nexport interface FieldLabelProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Size for the field label. */\n size?: 'small' | 'normal' | 'medium' | 'large';\n /** Text color for the label. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma color for the label. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color for the label. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Field label content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the FieldBody component.\n */\nexport interface FieldBodyProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Text color for the field body. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma color for the field body. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Background color for the field body. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Field body content. */\n children?: React.ReactNode;\n}\n\n/**\n * FieldLabel component for rendering a Bulma field label. It renders the\n * label column of a horizontal `Field` (a `div` with the `field-label` class),\n * not a `<label>`, so text placed straight in it names nothing. Put a `<label>`\n * with the `label` class inside it and point its `htmlFor` at the control's\n * `id`, or give the horizontal `Field` a `label` prop, which renders this\n * column and its `<label>` for you. A `<label>` you put here names the\n * control through its `htmlFor` alone: a range `Slider`'s thumbs and an\n * `Autocomplete`'s suggestion list point `aria-labelledby` at a `Field`'s\n * label only when its `label` prop renders it and it names the control.\n * Where it would not name the control on its own, as in an inner `Field`,\n * pass `labelProps={{ htmlFor, id }}` with a matching `id` on the control.\n *\n * @function\n * @param {FieldLabelProps} props - Props for the FieldLabel component.\n * @returns {JSX.Element} The rendered field label.\n *\n * @example\n * <FieldLabel size=\"normal\">\n * <label className=\"label\" htmlFor=\"name\">Name</label>\n * </FieldLabel>\n */\nexport const FieldLabel: React.FC<FieldLabelProps> = ({\n size,\n textColor,\n bgColor,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('field-label', {\n [`is-${size}`]: !!size,\n });\n const fieldLabelClass = classNames(mainClass, bulmaHelperClasses, className);\n // Spread ...props and ...rest so custom props like data-testid are included\n return (\n <div className={fieldLabelClass} {...props} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * FieldBody component for rendering Bulma field body.\n *\n * @function\n * @param {FieldBodyProps} props - Props for the FieldBody component.\n * @returns {JSX.Element} The rendered field body.\n *\n * @example\n * <FieldBody><input className=\"input\" /></FieldBody>\n */\nexport const FieldBody: React.FC<FieldBodyProps> = ({\n textColor,\n bgColor,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('field-body');\n const fieldBodyClass = classNames(mainClass, bulmaHelperClasses, className);\n // Spread ...props and ...rest so custom props like data-testid are included\n return (\n <div className={fieldBodyClass} {...props} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * The `Field` component is a Bulma-styled form field container.\n *\n * @function\n * @param {FieldProps} props - Props for the Field component.\n * @returns {JSX.Element} The rendered field container.\n * @see {@link https://bulma.io/documentation/form/general/#field | Bulma Field documentation}\n *\n * @example\n * // Labelled field — the label auto-associates with the composed base\n * <Field label=\"Email\">\n * <Control>\n * <InputBase type=\"email\" />\n * </Control>\n * </Field>\n *\n * @example\n * // Horizontal field\n * <Field horizontal label=\"Name\">\n * <Control>\n * <InputBase />\n * </Control>\n * </Field>\n */\nconst FieldComponent: React.FC<FieldProps> = ({\n horizontal,\n grouped,\n hasAddons,\n narrow,\n label,\n labelSize,\n labelProps,\n textColor,\n color: _fieldColor,\n bgColor,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('field', {\n 'is-horizontal': horizontal,\n 'has-addons': !!hasAddons,\n 'has-addons-centered': hasAddons === 'centered',\n 'has-addons-right': hasAddons === 'right',\n 'is-narrow': narrow,\n 'is-grouped':\n grouped === true ||\n grouped === 'centered' ||\n grouped === 'right' ||\n grouped === 'multiline',\n 'is-grouped-centered': grouped === 'centered',\n 'is-grouped-right': grouped === 'right',\n 'is-grouped-multiline': grouped === 'multiline',\n });\n const fieldClass = classNames(mainClass, bulmaHelperClasses, className);\n\n // Default labelSize to 'normal' when horizontal for proper baseline alignment\n const effectiveLabelSize = labelSize ?? (horizontal ? 'normal' : undefined);\n\n const labelClass = usePrefixedClassNames('label');\n\n // Auto-associate the label with a single composed base control (#495): the\n // label points at a generated id shared via context, which a composed base\n // adopts when the user supplied no id of their own.\n // Presence semantics on htmlFor — even an explicit `htmlFor: undefined`\n // means the caller owns the association. Grouped/addons fields hold several\n // controls, so no single association is generated for them.\n const generatedId = useId();\n const userWiredLabel = !!labelProps && 'htmlFor' in labelProps;\n const targetId =\n label && !userWiredLabel && !grouped && !hasAddons\n ? generatedId\n : undefined;\n // A group control (Radios, Checkboxes, Rate, DateRangeInput and its base)\n // cannot take that `for`, so it points `aria-labelledby` at the label\n // itself (#939).\n // The label gets an id whenever the association is on, unless the caller\n // gave it one.\n const labelId =\n labelProps?.id ?? (targetId ? `${targetId}-label` : undefined);\n // What the rendered label's `for` points at, generated or the caller's, and\n // the id it renders with, so a control can tell when a label wired by hand\n // names it and point at that label. An unlabeled Field passes on its\n // parent's. Unlike `targetId`, a label wired by hand passes on its own in\n // `grouped`/`hasAddons` Fields too, on purpose: those only stop the Field\n // picking one control out of several, and the caller's `for` has picked\n // one, so a range Slider or Autocomplete it names points at that label in\n // a row as well. A group reads the label element id below instead, which\n // stays off for a label wired by hand, since no group takes its `for`.\n const inheritedLabelFor = useFieldLabelFor();\n const labelForTarget = userWiredLabel ? labelProps.htmlFor : targetId;\n const ownLabelFor = useMemo(\n () => ({ htmlFor: labelForTarget, id: labelId }),\n [labelForTarget, labelId]\n );\n const labelFor = label ? ownLabelFor : inheritedLabelFor;\n\n let renderedLabel = null;\n if (label) {\n if (horizontal) {\n renderedLabel = (\n <FieldLabel size={effectiveLabelSize}>\n <label\n htmlFor={targetId}\n {...labelProps}\n id={labelId}\n className={classNames(labelClass, labelProps?.className)}\n style={labelProps?.style}\n >\n {label}\n </label>\n </FieldLabel>\n );\n } else {\n renderedLabel = (\n <label\n htmlFor={targetId}\n {...labelProps}\n id={labelId}\n className={classNames(labelClass, labelProps?.className)}\n style={{ display: 'block', ...(labelProps?.style || {}) }}\n >\n {label}\n </label>\n );\n }\n }\n\n // If horizontal, wrap children in FieldBody (unless the user already provided\n // a FieldBody — either as the single child, or as one element among siblings\n // like <Field.Label/> + <Field.Body/>).\n let content = children;\n if (horizontal) {\n const isFieldBody = (c: React.ReactNode): boolean =>\n React.isValidElement(c) &&\n // @ts-expect-error displayName isn't on the public type\n (c.type === FieldBody || c.type?.displayName === 'FieldBody');\n const isFieldLabel = (c: React.ReactNode): boolean =>\n React.isValidElement(c) &&\n // @ts-expect-error displayName isn't on the public type\n (c.type === FieldLabel || c.type?.displayName === 'FieldLabel');\n const childArray = React.Children.toArray(children);\n const userProvidedStructure = childArray.some(\n c => isFieldBody(c) || isFieldLabel(c)\n );\n if (userProvidedStructure) {\n content = children;\n } else {\n content = <FieldBody>{children}</FieldBody>;\n }\n }\n\n return (\n <FieldProvider value={true}>\n <FieldLabelIdProvider value={targetId}>\n <FieldLabelElementIdProvider value={targetId ? labelId : undefined}>\n <FieldLabelForProvider value={labelFor}>\n <div className={fieldClass} {...rest}>\n {renderedLabel}\n {content}\n </div>\n </FieldLabelForProvider>\n </FieldLabelElementIdProvider>\n </FieldLabelIdProvider>\n </FieldProvider>\n );\n};\n\nFieldLabel.displayName = 'FieldLabel';\nFieldBody.displayName = 'FieldBody';\n\nexport const Field = withSubComponents(\n FieldComponent,\n {\n Label: FieldLabel,\n Body: FieldBody,\n Control,\n },\n 'Field'\n);\n\nexport default Field;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -154,27 +154,32 @@ const FieldLabelIdProvider = FieldLabelIdContext.Provider;
|
|
|
154
154
|
const FieldLabelElementIdContext = createContext(undefined);
|
|
155
155
|
/**
|
|
156
156
|
* The id of a labeled Field's own `<label>`, for a group control (Radios,
|
|
157
|
-
* Checkboxes, Rate, DateRangeInput) to point
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* `useAutoLabelId`.
|
|
157
|
+
* Checkboxes, Rate, DateRangeInput and DateRangeInputBase) to point
|
|
158
|
+
* `aria-labelledby` at, since a group cannot take the label's `htmlFor`
|
|
159
|
+
* (#939, #1005). Set under the same conditions as
|
|
160
|
+
* {@link useFieldLabelId}. Consumed through `useAutoLabelledBy`.
|
|
162
161
|
* Internal; not part of the public API.
|
|
163
162
|
*/
|
|
164
163
|
const useFieldLabelElementId = () => useContext(FieldLabelElementIdContext);
|
|
165
164
|
/** Provider for the Field label's own id, used internally by Field. */
|
|
166
165
|
const FieldLabelElementIdProvider = FieldLabelElementIdContext.Provider;
|
|
167
|
-
const FieldLabelForContext = createContext(
|
|
166
|
+
const FieldLabelForContext = createContext({});
|
|
168
167
|
/**
|
|
169
|
-
*
|
|
170
|
-
* generated
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
168
|
+
* The nearest labeled Field's `<label>`: what it points `htmlFor` at, the id
|
|
169
|
+
* it generated or the caller's own `labelProps.htmlFor`, and the id the label
|
|
170
|
+
* renders with, if it has one. An unlabeled Field passes both through
|
|
171
|
+
* together, so a control in the inner Field of a horizontal layout can tell
|
|
172
|
+
* the outer label names it, and point at that label by its id, as a range
|
|
173
|
+
* Slider's thumbs (#981) and Autocomplete's suggestion list (#998) do. The
|
|
174
|
+
* `htmlFor` is only ever compared with a control's own id, never adopted, so
|
|
175
|
+
* it hands out no id for a control. The `id` is set only while that label
|
|
176
|
+
* renders with it. Unlike {@link useFieldLabelId}, it is set in a `grouped`
|
|
177
|
+
* or `hasAddons` Field too, so a label wired by hand names the control its
|
|
178
|
+
* `for` picks in those rows as well. Consumed through `useAutoLabelId`.
|
|
179
|
+
* Internal; not part of the public API.
|
|
175
180
|
*/
|
|
176
181
|
const useFieldLabelFor = () => useContext(FieldLabelForContext);
|
|
177
|
-
/** Provider for the Field label's `htmlFor` target, used internally by Field. */
|
|
182
|
+
/** Provider for the Field label's `htmlFor` target and id, used internally by Field. */
|
|
178
183
|
const FieldLabelForProvider = FieldLabelForContext.Provider;
|
|
179
184
|
const RadiosContext = createContext(undefined);
|
|
180
185
|
const CheckboxesContext = createContext(undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormContext.js","sources":["../../../src/form/FormContext.tsx"],"sourcesContent":["import React, { createContext, useContext } from 'react';\nimport { warnOnce } from '../helpers/devWarnings';\nimport type { ControlBaseProps } from './Control';\n\nconst FieldContext = createContext(false);\nconst ControlContext = createContext(false);\n\n/**\n * Hook to detect if the component is inside a Field wrapper.\n * Form components use this to skip rendering their own Field.\n */\nexport const useInsideField = () => useContext(FieldContext);\n\n/**\n * Hook to detect if the component is inside a Control wrapper.\n * Form components use this to skip rendering their own Control.\n */\nexport const useInsideControl = () => useContext(ControlContext);\n\n/** Provider for Field context — used internally by Field component. */\nexport const FieldProvider = FieldContext.Provider;\n\n/** Provider for Control context — used internally by Control component. */\nexport const ControlProvider = ControlContext.Provider;\n\n/** The wrapper props that change what its own `Field` renders. */\ninterface FieldShapingProps {\n /** Rendered as the `Field`'s label. */\n label?: React.ReactNode;\n /** Rendered as help text after the widget. */\n message?: React.ReactNode;\n /** Lays the `Field` out horizontally. */\n horizontal?: boolean;\n /** Set on the `Field` as its class. */\n fieldClassName?: string;\n}\n\ninterface OwnFieldOptions extends FieldShapingProps {\n /** `useInsideField()` as the wrapper read it. */\n insideField: boolean;\n /** `useInsideControl()` as the wrapper read it. */\n insideControl: boolean;\n}\n\n// Each Field-shaping prop, with what takes its place on a `Field` the caller\n// wraps around the `Control`. `message` needs nothing there, because the\n// wrapper still renders it inside `Field > Control`. The other Field-level\n// props (`labelSize`, `labelProps`, `messageColor`) change nothing unless a\n// `label` or `message` renders, so on their own they keep no `Field`.\n// `bare-control.test.tsx` holds this list to what each wrapper hands its\n// `Field` and to which props change its markup, so a new Field-level prop\n// fails there until it is sorted into one group or the other.\nconst FIELD_SHAPING: ReadonlyArray<\n [keyof FieldShapingProps, string | undefined]\n> = [\n ['label', 'label'],\n ['message', undefined],\n ['horizontal', 'horizontal'],\n ['fieldClassName', 'className (for fieldClassName)'],\n];\n\n/** `a`, `a and b`, `a, b and c`. */\nconst listOf = (items: string[]): string =>\n items.length > 1\n ? `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`\n : items[0];\n\n/**\n * Whether a convenience form wrapper renders a `Field` of its own (#905).\n * Never inside an outer `Field`. Inside a `Control` with no `Field` around\n * it, a `Field` of its own would put a `.field` inside the `.control`, where\n * Bulma's control styles break (its icon rules are sibling selectors on the\n * input). So it renders one there only when a prop that shapes the `Field`'s\n * markup is set (`label`, `message`, `horizontal`, `fieldClassName`), keeping\n * the markup it always had, and warns in development that the fix is a\n * `Field` around that `Control`. A prop counts when it is truthy, the same\n * test that decides whether it changes the `Field`'s output.\n * Internal; not part of the public API.\n */\nexport const rendersOwnField = (\n component: string,\n options: OwnFieldOptions\n): boolean => {\n if (options.insideField) return false;\n if (!options.insideControl) return true;\n const held = FIELD_SHAPING.filter(([prop]) => options[prop]);\n if (held.length === 0) return false;\n const names = held.map(([prop]) => prop);\n const moved = held\n .map(([, onField]) => onField)\n .filter((onField): onField is string => onField !== undefined);\n warnOnce(\n `${component}:Field-in-bare-Control:${names.join('+')}`,\n `[bestax-bulma] <${component} ${names.join(' ')}> inside a <Control> ` +\n `with no <Field> around it renders its own <Field> for ` +\n `${names.length > 1 ? 'those props' : 'that prop'}, which puts a ` +\n `.field inside the .control, a nesting Bulma's styles are not ` +\n `written for. Wrap the <Control> in a <Field> instead` +\n (moved.length > 0 ? `, and set ${listOf(moved)} on that <Field>.` : '.')\n );\n return true;\n};\n\n/** The props a convenience form wrapper hands its own `Control`. Internal. */\nexport interface ControlLevelProps {\n /** Shows the `Control`'s loading spinner. */\n isLoading?: boolean;\n /** The `Control`'s left icon. */\n iconLeft?: ControlBaseProps['iconLeft'];\n /** Shortcut for the left icon's name. */\n iconLeftName?: string;\n /** Shortcut for the left icon's size. */\n iconLeftSize?: ControlBaseProps['iconLeftSize'];\n /** The `Control`'s right icon. */\n iconRight?: ControlBaseProps['iconRight'];\n /** Shortcut for the right icon's name. */\n iconRightName?: string;\n /** Shortcut for the right icon's size. */\n iconRightSize?: ControlBaseProps['iconRightSize'];\n /** Reserves the `Control`'s left icon space. */\n hasIconsLeft?: boolean;\n /** Reserves the `Control`'s right icon space. */\n hasIconsRight?: boolean;\n /** Expands the `Control`. */\n isExpanded?: boolean;\n /** Set on the `Control` as its `size`. */\n controlSize?: ControlBaseProps['size'];\n /** Set on the `Control` as its class. */\n controlClassName?: string;\n}\n\ninterface OwnControlOptions extends ControlLevelProps {\n /** `useInsideControl()` as the wrapper read it. */\n insideControl: boolean;\n /** A picker's `inline`, which renders no `Control` inside one or out. */\n inline?: boolean;\n /**\n * The left glyph the wrapper's own `Control` shows when the caller sets no\n * `iconLeftName`; read only then. `bare-control.test.tsx` reads that glyph\n * from what each wrapper hands its own `Control`, so a wrapper that gains\n * one fails there until it passes it here.\n */\n defaultIconLeftName?: string;\n}\n\n// Each Control-level prop, with what takes its place on the `Control` the\n// caller wrapped around the wrapper. `bare-control.test.tsx` holds this to\n// what each wrapper hands its own `Control`, so a new Control-level prop\n// fails there until it is added here and passed to `rendersOwnControl`.\nconst ON_CONTROL: Record<keyof ControlLevelProps, string> = {\n isLoading: 'isLoading',\n iconLeft: 'iconLeft',\n iconLeftName: 'iconLeftName',\n iconLeftSize: 'iconLeftSize',\n iconRight: 'iconRight',\n iconRightName: 'iconRightName',\n iconRightSize: 'iconRightSize',\n hasIconsLeft: 'hasIconsLeft',\n hasIconsRight: 'hasIconsRight',\n isExpanded: 'isExpanded',\n controlSize: 'size (for controlSize)',\n controlClassName: 'className (for controlClassName)',\n};\n\n/**\n * Whether a convenience form wrapper renders a `Control` of its own (#921):\n * only outside one. Inside a `Control` it renders none, so the props it\n * would have handed its own do nothing there, and it warns in development,\n * naming them and saying to set them on that `Control`. An `inline` picker\n * renders none in either place, so it drops them inside a `Control` or not,\n * and its warning says so without pointing at a `Control`. A wrapper passes\n * only the props it hands its own `Control`, as the caller gave them, so a\n * default the wrapper fills in itself never warns. A prop counts when it is\n * truthy, since a falsy one would change nothing on a `Control` either.\n * `iconLeftSize` and `hasIconsLeft` show nothing on a `Control` without a\n * glyph, so when they move and the caller chose no left icon, the advice\n * names the wrapper's default glyph too, and following it draws what the\n * wrapper's own `Control` did.\n * Internal; not part of the public API.\n */\nexport const rendersOwnControl = (\n component: string,\n options: OwnControlOptions\n): boolean => {\n if (!options.inline && !options.insideControl) return true;\n const held = (\n Object.keys(ON_CONTROL) as Array<keyof ControlLevelProps>\n ).filter(prop => options[prop]);\n if (held.length === 0) return false;\n const names = held.join(' ');\n const doNothing = held.length > 1 ? 'those props do' : 'that prop does';\n let message: string;\n if (options.inline) {\n message =\n `[bestax-bulma] <${component} inline ${names}> renders no <Control> ` +\n `in inline mode, inside a <Control> or not, so ${doNothing} ` +\n `nothing. Leave ${held.length > 1 ? 'them' : 'it'} out of an ` +\n `inline picker.`;\n } else {\n const toSet = held.map(prop => ON_CONTROL[prop]);\n const needsGlyph =\n (options.iconLeftSize || options.hasIconsLeft) &&\n !options.iconLeft &&\n options.iconLeftName === undefined &&\n options.defaultIconLeftName;\n if (needsGlyph) {\n toSet.push(\n `iconLeftName=\"${options.defaultIconLeftName}\" (its default icon)`\n );\n }\n message =\n `[bestax-bulma] <${component} ${names}> inside a <Control> renders ` +\n `no <Control> of its own, so ${doNothing} nothing there. Set ` +\n `${listOf(toSet)} on that <Control> instead.`;\n }\n // Keyed by the message itself: the props named do not settle the advice\n // (an empty `iconLeftName` and an unset one name the same props), so two\n // calls that would advise differently must not share a key.\n warnOnce(message, message);\n return false;\n};\n\nconst FieldLabelIdContext = createContext<string | undefined>(undefined);\n\n/**\n * The id a labeled Field wants its single composed control to adopt (#495).\n * `undefined` outside a Field, in unlabeled/grouped/addons Fields, or when the\n * user took over the association with an explicit `labelProps.htmlFor`.\n * Consumed by the single-control bases (InputBase, SelectBase, TextAreaBase,\n * and the date and time picker bases unless inline, #968) and, through\n * `useAutoLabelId`, by the convenience inputs that render an input of their\n * own (#939). Internal; not part of the public API.\n */\nexport const useFieldLabelId = () => useContext(FieldLabelIdContext);\n\n/** Provider for the Field label-target id — used internally by Field. */\nexport const FieldLabelIdProvider = FieldLabelIdContext.Provider;\n\nconst FieldLabelElementIdContext = createContext<string | undefined>(undefined);\n\n/**\n * The id of a labeled Field's own `<label>`, for a group control (Radios,\n * Checkboxes, Rate, DateRangeInput) to point `aria-labelledby` at, since a group cannot take\n * the label's `htmlFor` (#939), and for a range Slider's thumbs, which each\n * need the label in a name of their own (#981). Set under the same conditions\n * as {@link useFieldLabelId}. Consumed through `useAutoLabelledBy` and\n * `useAutoLabelId`.\n * Internal; not part of the public API.\n */\nexport const useFieldLabelElementId = () =>\n useContext(FieldLabelElementIdContext);\n\n/** Provider for the Field label's own id, used internally by Field. */\nexport const FieldLabelElementIdProvider = FieldLabelElementIdContext.Provider;\n\nconst FieldLabelForContext = createContext<string | undefined>(undefined);\n\n/**\n * What the nearest labeled Field's `<label>` points `htmlFor` at: the id it\n * generated, or the caller's own `labelProps.htmlFor`. An unlabeled Field\n * passes it through, so a control in the inner Field of a horizontal layout\n * can tell the outer label names it. Only ever compared with a control's own\n * id, never adopted, so it hands out no id. Internal; not part of the public\n * API.\n */\nexport const useFieldLabelFor = () => useContext(FieldLabelForContext);\n\n/** Provider for the Field label's `htmlFor` target, used internally by Field. */\nexport const FieldLabelForProvider = FieldLabelForContext.Provider;\n\n/**\n * Shape of the Radios group context. The group provides:\n * - `name`: shared form field name (Stage 1)\n * - `value`: currently-selected radio value (Stage 2 — group-managed selection)\n * - `onChange`: dispatched by child Radios when clicked (Stage 2)\n *\n * Group sets `value`/`onChange` only when actively managing selection\n * (i.e., the user passed `value`, `defaultValue`, or `onChange` to `<Radios>`).\n * When only `name` is provided, the group is in \"name-only\" mode and child\n * Radios manage their own checked state independently.\n */\nexport interface RadiosGroupContextValue {\n name?: string;\n value?: string;\n onChange?: (value: string) => void;\n}\n\n/**\n * Shape of the Checkboxes group context. Like Radios but with array semantics\n * for multi-select.\n */\nexport interface CheckboxesGroupContextValue {\n name?: string;\n value?: string[];\n onChange?: (values: string[]) => void;\n}\n\nconst RadiosContext = createContext<RadiosGroupContextValue | undefined>(\n undefined\n);\nconst CheckboxesContext = createContext<\n CheckboxesGroupContextValue | undefined\n>(undefined);\n\n/**\n * Hook to read the full surrounding `<Radios>` group context (name + selection).\n * Returns `undefined` when not inside a `<Radios>` group.\n */\nexport const useRadiosGroup = () => useContext(RadiosContext);\n\n/**\n * Hook to read the full surrounding `<Checkboxes>` group context.\n * Returns `undefined` when not inside a `<Checkboxes>` group.\n */\nexport const useCheckboxesGroup = () => useContext(CheckboxesContext);\n\n/**\n * Hook to read just the shared `name` from a surrounding `<Radios>` group.\n * Child `<Radio>` components fall back to this when no local `name` prop is set.\n * Returns `undefined` outside of a `<Radios>` group.\n */\nexport const useRadiosName = () => useRadiosGroup()?.name;\n\n/**\n * Hook to read just the shared `name` from a surrounding `<Checkboxes>` group.\n * Returns `undefined` outside of a `<Checkboxes>` group.\n */\nexport const useCheckboxesName = () => useCheckboxesGroup()?.name;\n\n/** Provider for the Radios group context — used internally by Radios. */\nexport const RadiosProvider = RadiosContext.Provider;\n\n/** Provider for the Checkboxes group context — used internally by Checkboxes. */\nexport const CheckboxesProvider = CheckboxesContext.Provider;\n\n// --- Backward-compat aliases (Stage 1 names) -----------------------------\n// Internal callers may still import these. Both still work because they refer\n// to the same providers/hooks under the new shape.\n\n/** @deprecated Use `RadiosProvider` (provides {name, value, onChange}). */\nexport const RadiosNameProvider = RadiosProvider;\n\n/** @deprecated Use `CheckboxesProvider` (provides {name, value, onChange}). */\nexport const CheckboxesNameProvider = CheckboxesProvider;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormContext.js","sources":["../../../src/form/FormContext.tsx"],"sourcesContent":["import React, { createContext, useContext } from 'react';\nimport { warnOnce } from '../helpers/devWarnings';\nimport type { ControlBaseProps } from './Control';\n\nconst FieldContext = createContext(false);\nconst ControlContext = createContext(false);\n\n/**\n * Hook to detect if the component is inside a Field wrapper.\n * Form components use this to skip rendering their own Field.\n */\nexport const useInsideField = () => useContext(FieldContext);\n\n/**\n * Hook to detect if the component is inside a Control wrapper.\n * Form components use this to skip rendering their own Control.\n */\nexport const useInsideControl = () => useContext(ControlContext);\n\n/** Provider for Field context — used internally by Field component. */\nexport const FieldProvider = FieldContext.Provider;\n\n/** Provider for Control context — used internally by Control component. */\nexport const ControlProvider = ControlContext.Provider;\n\n/** The wrapper props that change what its own `Field` renders. */\ninterface FieldShapingProps {\n /** Rendered as the `Field`'s label. */\n label?: React.ReactNode;\n /** Rendered as help text after the widget. */\n message?: React.ReactNode;\n /** Lays the `Field` out horizontally. */\n horizontal?: boolean;\n /** Set on the `Field` as its class. */\n fieldClassName?: string;\n}\n\ninterface OwnFieldOptions extends FieldShapingProps {\n /** `useInsideField()` as the wrapper read it. */\n insideField: boolean;\n /** `useInsideControl()` as the wrapper read it. */\n insideControl: boolean;\n}\n\n// Each Field-shaping prop, with what takes its place on a `Field` the caller\n// wraps around the `Control`. `message` needs nothing there, because the\n// wrapper still renders it inside `Field > Control`. The other Field-level\n// props (`labelSize`, `labelProps`, `messageColor`) change nothing unless a\n// `label` or `message` renders, so on their own they keep no `Field`.\n// `bare-control.test.tsx` holds this list to what each wrapper hands its\n// `Field` and to which props change its markup, so a new Field-level prop\n// fails there until it is sorted into one group or the other.\nconst FIELD_SHAPING: ReadonlyArray<\n [keyof FieldShapingProps, string | undefined]\n> = [\n ['label', 'label'],\n ['message', undefined],\n ['horizontal', 'horizontal'],\n ['fieldClassName', 'className (for fieldClassName)'],\n];\n\n/** `a`, `a and b`, `a, b and c`. */\nconst listOf = (items: string[]): string =>\n items.length > 1\n ? `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`\n : items[0];\n\n/**\n * Whether a convenience form wrapper renders a `Field` of its own (#905).\n * Never inside an outer `Field`. Inside a `Control` with no `Field` around\n * it, a `Field` of its own would put a `.field` inside the `.control`, where\n * Bulma's control styles break (its icon rules are sibling selectors on the\n * input). So it renders one there only when a prop that shapes the `Field`'s\n * markup is set (`label`, `message`, `horizontal`, `fieldClassName`), keeping\n * the markup it always had, and warns in development that the fix is a\n * `Field` around that `Control`. A prop counts when it is truthy, the same\n * test that decides whether it changes the `Field`'s output.\n * Internal; not part of the public API.\n */\nexport const rendersOwnField = (\n component: string,\n options: OwnFieldOptions\n): boolean => {\n if (options.insideField) return false;\n if (!options.insideControl) return true;\n const held = FIELD_SHAPING.filter(([prop]) => options[prop]);\n if (held.length === 0) return false;\n const names = held.map(([prop]) => prop);\n const moved = held\n .map(([, onField]) => onField)\n .filter((onField): onField is string => onField !== undefined);\n warnOnce(\n `${component}:Field-in-bare-Control:${names.join('+')}`,\n `[bestax-bulma] <${component} ${names.join(' ')}> inside a <Control> ` +\n `with no <Field> around it renders its own <Field> for ` +\n `${names.length > 1 ? 'those props' : 'that prop'}, which puts a ` +\n `.field inside the .control, a nesting Bulma's styles are not ` +\n `written for. Wrap the <Control> in a <Field> instead` +\n (moved.length > 0 ? `, and set ${listOf(moved)} on that <Field>.` : '.')\n );\n return true;\n};\n\n/** The props a convenience form wrapper hands its own `Control`. Internal. */\nexport interface ControlLevelProps {\n /** Shows the `Control`'s loading spinner. */\n isLoading?: boolean;\n /** The `Control`'s left icon. */\n iconLeft?: ControlBaseProps['iconLeft'];\n /** Shortcut for the left icon's name. */\n iconLeftName?: string;\n /** Shortcut for the left icon's size. */\n iconLeftSize?: ControlBaseProps['iconLeftSize'];\n /** The `Control`'s right icon. */\n iconRight?: ControlBaseProps['iconRight'];\n /** Shortcut for the right icon's name. */\n iconRightName?: string;\n /** Shortcut for the right icon's size. */\n iconRightSize?: ControlBaseProps['iconRightSize'];\n /** Reserves the `Control`'s left icon space. */\n hasIconsLeft?: boolean;\n /** Reserves the `Control`'s right icon space. */\n hasIconsRight?: boolean;\n /** Expands the `Control`. */\n isExpanded?: boolean;\n /** Set on the `Control` as its `size`. */\n controlSize?: ControlBaseProps['size'];\n /** Set on the `Control` as its class. */\n controlClassName?: string;\n}\n\ninterface OwnControlOptions extends ControlLevelProps {\n /** `useInsideControl()` as the wrapper read it. */\n insideControl: boolean;\n /** A picker's `inline`, which renders no `Control` inside one or out. */\n inline?: boolean;\n /**\n * The left glyph the wrapper's own `Control` shows when the caller sets no\n * `iconLeftName`; read only then. `bare-control.test.tsx` reads that glyph\n * from what each wrapper hands its own `Control`, so a wrapper that gains\n * one fails there until it passes it here.\n */\n defaultIconLeftName?: string;\n}\n\n// Each Control-level prop, with what takes its place on the `Control` the\n// caller wrapped around the wrapper. `bare-control.test.tsx` holds this to\n// what each wrapper hands its own `Control`, so a new Control-level prop\n// fails there until it is added here and passed to `rendersOwnControl`.\nconst ON_CONTROL: Record<keyof ControlLevelProps, string> = {\n isLoading: 'isLoading',\n iconLeft: 'iconLeft',\n iconLeftName: 'iconLeftName',\n iconLeftSize: 'iconLeftSize',\n iconRight: 'iconRight',\n iconRightName: 'iconRightName',\n iconRightSize: 'iconRightSize',\n hasIconsLeft: 'hasIconsLeft',\n hasIconsRight: 'hasIconsRight',\n isExpanded: 'isExpanded',\n controlSize: 'size (for controlSize)',\n controlClassName: 'className (for controlClassName)',\n};\n\n/**\n * Whether a convenience form wrapper renders a `Control` of its own (#921):\n * only outside one. Inside a `Control` it renders none, so the props it\n * would have handed its own do nothing there, and it warns in development,\n * naming them and saying to set them on that `Control`. An `inline` picker\n * renders none in either place, so it drops them inside a `Control` or not,\n * and its warning says so without pointing at a `Control`. A wrapper passes\n * only the props it hands its own `Control`, as the caller gave them, so a\n * default the wrapper fills in itself never warns. A prop counts when it is\n * truthy, since a falsy one would change nothing on a `Control` either.\n * `iconLeftSize` and `hasIconsLeft` show nothing on a `Control` without a\n * glyph, so when they move and the caller chose no left icon, the advice\n * names the wrapper's default glyph too, and following it draws what the\n * wrapper's own `Control` did.\n * Internal; not part of the public API.\n */\nexport const rendersOwnControl = (\n component: string,\n options: OwnControlOptions\n): boolean => {\n if (!options.inline && !options.insideControl) return true;\n const held = (\n Object.keys(ON_CONTROL) as Array<keyof ControlLevelProps>\n ).filter(prop => options[prop]);\n if (held.length === 0) return false;\n const names = held.join(' ');\n const doNothing = held.length > 1 ? 'those props do' : 'that prop does';\n let message: string;\n if (options.inline) {\n message =\n `[bestax-bulma] <${component} inline ${names}> renders no <Control> ` +\n `in inline mode, inside a <Control> or not, so ${doNothing} ` +\n `nothing. Leave ${held.length > 1 ? 'them' : 'it'} out of an ` +\n `inline picker.`;\n } else {\n const toSet = held.map(prop => ON_CONTROL[prop]);\n const needsGlyph =\n (options.iconLeftSize || options.hasIconsLeft) &&\n !options.iconLeft &&\n options.iconLeftName === undefined &&\n options.defaultIconLeftName;\n if (needsGlyph) {\n toSet.push(\n `iconLeftName=\"${options.defaultIconLeftName}\" (its default icon)`\n );\n }\n message =\n `[bestax-bulma] <${component} ${names}> inside a <Control> renders ` +\n `no <Control> of its own, so ${doNothing} nothing there. Set ` +\n `${listOf(toSet)} on that <Control> instead.`;\n }\n // Keyed by the message itself: the props named do not settle the advice\n // (an empty `iconLeftName` and an unset one name the same props), so two\n // calls that would advise differently must not share a key.\n warnOnce(message, message);\n return false;\n};\n\nconst FieldLabelIdContext = createContext<string | undefined>(undefined);\n\n/**\n * The id a labeled Field wants its single composed control to adopt (#495).\n * `undefined` outside a Field, in unlabeled/grouped/addons Fields, or when the\n * user took over the association with an explicit `labelProps.htmlFor`.\n * Consumed by the single-control bases (InputBase, SelectBase, TextAreaBase,\n * and the date and time picker bases unless inline, #968) and, through\n * `useAutoLabelId`, by the convenience inputs that render an input of their\n * own (#939). Internal; not part of the public API.\n */\nexport const useFieldLabelId = () => useContext(FieldLabelIdContext);\n\n/** Provider for the Field label-target id — used internally by Field. */\nexport const FieldLabelIdProvider = FieldLabelIdContext.Provider;\n\nconst FieldLabelElementIdContext = createContext<string | undefined>(undefined);\n\n/**\n * The id of a labeled Field's own `<label>`, for a group control (Radios,\n * Checkboxes, Rate, DateRangeInput and DateRangeInputBase) to point\n * `aria-labelledby` at, since a group cannot take the label's `htmlFor`\n * (#939, #1005). Set under the same conditions as\n * {@link useFieldLabelId}. Consumed through `useAutoLabelledBy`.\n * Internal; not part of the public API.\n */\nexport const useFieldLabelElementId = () =>\n useContext(FieldLabelElementIdContext);\n\n/** Provider for the Field label's own id, used internally by Field. */\nexport const FieldLabelElementIdProvider = FieldLabelElementIdContext.Provider;\n\n/** The nearest labeled Field's `<label>`, as {@link useFieldLabelFor} reads it. */\nexport interface FieldLabelFor {\n /** What the label's `htmlFor` points at, generated or the caller's. */\n htmlFor?: string;\n /** The id the label renders with, the caller's or a generated one, if any. */\n id?: string;\n}\n\nconst FieldLabelForContext = createContext<FieldLabelFor>({});\n\n/**\n * The nearest labeled Field's `<label>`: what it points `htmlFor` at, the id\n * it generated or the caller's own `labelProps.htmlFor`, and the id the label\n * renders with, if it has one. An unlabeled Field passes both through\n * together, so a control in the inner Field of a horizontal layout can tell\n * the outer label names it, and point at that label by its id, as a range\n * Slider's thumbs (#981) and Autocomplete's suggestion list (#998) do. The\n * `htmlFor` is only ever compared with a control's own id, never adopted, so\n * it hands out no id for a control. The `id` is set only while that label\n * renders with it. Unlike {@link useFieldLabelId}, it is set in a `grouped`\n * or `hasAddons` Field too, so a label wired by hand names the control its\n * `for` picks in those rows as well. Consumed through `useAutoLabelId`.\n * Internal; not part of the public API.\n */\nexport const useFieldLabelFor = () => useContext(FieldLabelForContext);\n\n/** Provider for the Field label's `htmlFor` target and id, used internally by Field. */\nexport const FieldLabelForProvider = FieldLabelForContext.Provider;\n\n/**\n * Shape of the Radios group context. The group provides:\n * - `name`: shared form field name (Stage 1)\n * - `value`: currently-selected radio value (Stage 2 — group-managed selection)\n * - `onChange`: dispatched by child Radios when clicked (Stage 2)\n *\n * Group sets `value`/`onChange` only when actively managing selection\n * (i.e., the user passed `value`, `defaultValue`, or `onChange` to `<Radios>`).\n * When only `name` is provided, the group is in \"name-only\" mode and child\n * Radios manage their own checked state independently.\n */\nexport interface RadiosGroupContextValue {\n name?: string;\n value?: string;\n onChange?: (value: string) => void;\n}\n\n/**\n * Shape of the Checkboxes group context. Like Radios but with array semantics\n * for multi-select.\n */\nexport interface CheckboxesGroupContextValue {\n name?: string;\n value?: string[];\n onChange?: (values: string[]) => void;\n}\n\nconst RadiosContext = createContext<RadiosGroupContextValue | undefined>(\n undefined\n);\nconst CheckboxesContext = createContext<\n CheckboxesGroupContextValue | undefined\n>(undefined);\n\n/**\n * Hook to read the full surrounding `<Radios>` group context (name + selection).\n * Returns `undefined` when not inside a `<Radios>` group.\n */\nexport const useRadiosGroup = () => useContext(RadiosContext);\n\n/**\n * Hook to read the full surrounding `<Checkboxes>` group context.\n * Returns `undefined` when not inside a `<Checkboxes>` group.\n */\nexport const useCheckboxesGroup = () => useContext(CheckboxesContext);\n\n/**\n * Hook to read just the shared `name` from a surrounding `<Radios>` group.\n * Child `<Radio>` components fall back to this when no local `name` prop is set.\n * Returns `undefined` outside of a `<Radios>` group.\n */\nexport const useRadiosName = () => useRadiosGroup()?.name;\n\n/**\n * Hook to read just the shared `name` from a surrounding `<Checkboxes>` group.\n * Returns `undefined` outside of a `<Checkboxes>` group.\n */\nexport const useCheckboxesName = () => useCheckboxesGroup()?.name;\n\n/** Provider for the Radios group context — used internally by Radios. */\nexport const RadiosProvider = RadiosContext.Provider;\n\n/** Provider for the Checkboxes group context — used internally by Checkboxes. */\nexport const CheckboxesProvider = CheckboxesContext.Provider;\n\n// --- Backward-compat aliases (Stage 1 names) -----------------------------\n// Internal callers may still import these. Both still work because they refer\n// to the same providers/hooks under the new shape.\n\n/** @deprecated Use `RadiosProvider` (provides {name, value, onChange}). */\nexport const RadiosNameProvider = RadiosProvider;\n\n/** @deprecated Use `CheckboxesProvider` (provides {name, value, onChange}). */\nexport const CheckboxesNameProvider = CheckboxesProvider;\n"],"names":[],"mappings":"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"}
|