@allxsmith/bestax-bulma 5.27.6 → 5.27.8
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/DateInputBase.js +2 -3
- package/dist/esm/form/DateInputBase.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/DateTimeInputBase.js +2 -3
- package/dist/esm/form/DateTimeInputBase.js.map +1 -1
- package/dist/esm/form/Field.js +39 -7
- package/dist/esm/form/Field.js.map +1 -1
- package/dist/esm/form/FormContext.js +56 -11
- package/dist/esm/form/FormContext.js.map +1 -1
- package/dist/esm/form/InputBase.js +6 -5
- package/dist/esm/form/InputBase.js.map +1 -1
- package/dist/esm/form/SelectBase.js +7 -5
- package/dist/esm/form/SelectBase.js.map +1 -1
- package/dist/esm/form/TextAreaBase.js +6 -5
- package/dist/esm/form/TextAreaBase.js.map +1 -1
- package/dist/esm/form/TimeInputBase.js +2 -3
- package/dist/esm/form/TimeInputBase.js.map +1 -1
- package/dist/esm/form/useAutoLabelId.js +8 -3
- package/dist/esm/form/useAutoLabelId.js.map +1 -1
- package/dist/esm/helpers/Theme.js +87 -17
- package/dist/esm/helpers/Theme.js.map +1 -1
- package/dist/esm/helpers/devWarnings.js +8 -3
- package/dist/esm/helpers/devWarnings.js.map +1 -1
- package/dist/esm/helpers/useFlexboxClasses.js +1 -1
- package/dist/esm/helpers/useOtherClasses.js +1 -1
- package/dist/esm/helpers/useSpacingClasses.js +1 -1
- package/dist/esm/helpers/useTypographyClasses.js +1 -1
- package/dist/esm/helpers/useVisibilityClasses.js +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +226 -55
- package/dist/index.cjs.map +1 -1
- package/dist/types/elements/Notification.d.ts +5 -0
- package/dist/types/form/DateRangeInputBase.d.ts +5 -0
- package/dist/types/form/Field.d.ts +2 -2
- package/dist/types/form/FormContext.d.ts +50 -10
- package/dist/types/form/useAutoLabelId.d.ts +4 -2
- package/dist/types/helpers/Theme.d.ts +15 -1
- package/dist/types/helpers/devWarnings.d.ts +8 -0
- package/dist/types-cjs/elements/Notification.d.ts +5 -0
- package/dist/types-cjs/form/DateRangeInputBase.d.ts +5 -0
- package/dist/types-cjs/form/Field.d.ts +2 -2
- package/dist/types-cjs/form/FormContext.d.ts +50 -10
- package/dist/types-cjs/form/useAutoLabelId.d.ts +4 -2
- package/dist/types-cjs/helpers/Theme.d.ts +15 -1
- package/dist/types-cjs/helpers/devWarnings.d.ts +8 -0
- 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 +18 -18
- package/src/scss/elements/_index.scss +1 -0
- package/src/scss/elements/_notification.scss +69 -0
|
@@ -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). 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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"}
|
|
1
|
+
{"version":3,"file":"FormContext.js","sources":["../../../src/form/FormContext.tsx"],"sourcesContent":["import React, { createContext, useContext } from 'react';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\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 through `useFieldLabelTarget` by the single-control bases\n * (InputBase, SelectBase, TextAreaBase, and the date and time picker bases\n * unless inline, #968) and, through `useAutoLabelId`, by the convenience\n * inputs that render an input of their own (#939). Read it only through\n * those, which report what they take: a control that read it directly would\n * report nothing and lose its label (#1004), and\n * `__tests__/field-label-readers.test.ts` fails on one. Internal; not part of\n * 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. It keeps the generated id after the\n * label drops a `for` nothing took (#1004), which no control's id matches\n * then, so the value does not change under the content that reported it.\n * The `id` is set only while that label renders with it. Unlike\n * {@link useFieldLabelId}, it is set in a `grouped` or `hasAddons` Field\n * too, so a label wired by hand names the control its `for` picks in those\n * 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 * Records that one piece of a labeled Field's content took the label's\n * generated id, and returns the function that forgets it.\n */\ntype FieldLabelForReport = () => () => void;\n\nconst FieldLabelForReportContext = createContext<\n FieldLabelForReport | undefined\n>(undefined);\n\n/**\n * Tells the nearest labeled Field that this content took its generated id\n * while `takesFor` is true (#1004). Once the Field's content has mounted, its\n * label keeps the generated `for` only while something has said so, so the\n * label renders none over a group, a `Checkbox`, `Radio` or `Switch`, an\n * inner `Field`, an input with an `id` of its own, markup of your own, or\n * nothing at all. Anything that puts the id from {@link useFieldLabelId} on\n * an element has to say so, or the label drops the `for` that names it, and\n * content that takes no id has nothing to do. Set under the same conditions\n * as {@link useFieldLabelId}, so a label wired by hand and a `grouped` or\n * `hasAddons` Field hear nothing. It reports from a layout effect, which a\n * server never runs and a hydrating client runs only after its first render,\n * so that render writes the `for` the way the server did.\n * Internal; not part of the public API.\n */\nexport const useReportFieldLabelFor = (takesFor: boolean): void => {\n const report = useContext(FieldLabelForReportContext);\n useClientLayoutEffect(\n () => (takesFor ? report?.() : undefined),\n [report, takesFor]\n );\n};\n\n/** Provider for the labeled Field's report function, used internally by Field. */\nexport const FieldLabelForReportProvider = FieldLabelForReportContext.Provider;\n\n/**\n * The id a control with one input of its own renders with: the caller's\n * `id` when one arrived, otherwise the one a labeled Field offers (#495),\n * unless it has no input to put it on (`hasInput: false`, as in an `inline`\n * picker). It also tells that Field when it took the Field's id, through\n * {@link useReportFieldLabelFor}, so the label keeps its `for` (#1004). Used\n * by the single-control bases. Internal; not part of the public API.\n */\nexport const useFieldLabelTarget = (\n id: string | undefined,\n hasInput = true\n): string | undefined => {\n const fieldLabelId = useFieldLabelId();\n const target = id ?? (hasInput ? fieldLabelId : undefined);\n useReportFieldLabelFor(fieldLabelId !== undefined && target === fieldLabelId);\n return target;\n};\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":";;;;;AAKA,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC;AACzC,MAAM,cAAc,GAAG,aAAa,CAAC,KAAK,CAAC;AAE3C;;;AAGG;AACI,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,YAAY;AAE3D;;;AAGG;AACI,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,cAAc;AAE/D;AACO,MAAM,aAAa,GAAG,YAAY,CAAC;AAE1C;AACO,MAAM,eAAe,GAAG,cAAc,CAAC;AAqB9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,GAEf;IACF,CAAC,OAAO,EAAE,OAAO,CAAC;IAClB,CAAC,SAAS,EAAE,SAAS,CAAC;IACtB,CAAC,YAAY,EAAE,YAAY,CAAC;IAC5B,CAAC,gBAAgB,EAAE,gCAAgC,CAAC;CACrD;AAED;AACA,MAAM,MAAM,GAAG,CAAC,KAAe,KAC7B,KAAK,CAAC,MAAM,GAAG;MACX,CAAA,EAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,KAAA,EAAQ,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AACjE,MAAE,KAAK,CAAC,CAAC,CAAC;AAEd;;;;;;;;;;;AAWG;MACU,eAAe,GAAG,CAC7B,SAAiB,EACjB,OAAwB,KACb;IACX,IAAI,OAAO,CAAC,WAAW;AAAE,QAAA,OAAO,KAAK;IACrC,IAAI,CAAC,OAAO,CAAC,aAAa;AAAE,QAAA,OAAO,IAAI;AACvC,IAAA,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5D,IAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK;AACnC,IAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACxC,MAAM,KAAK,GAAG;SACX,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,OAAO;SAC5B,MAAM,CAAC,CAAC,OAAO,KAAwB,OAAO,KAAK,SAAS,CAAC;IAChE,QAAQ,CACN,GAAG,SAAS,CAAA,uBAAA,EAA0B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EACvD,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAA,EAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,qBAAA,CAAuB;QACpE,CAAA,sDAAA,CAAwD;AACxD,QAAA,CAAA,EAAG,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,aAAa,GAAG,WAAW,CAAA,eAAA,CAAiB;QAClE,CAAA,6DAAA,CAA+D;QAC/D,CAAA,oDAAA,CAAsD;SACrD,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,CAAA,UAAA,EAAa,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,GAAG,CAAC,CAC3E;AACD,IAAA,OAAO,IAAI;AACb;AA4CA;AACA;AACA;AACA;AACA,MAAM,UAAU,GAA4C;AAC1D,IAAA,SAAS,EAAE,WAAW;AACtB,IAAA,QAAQ,EAAE,UAAU;AACpB,IAAA,YAAY,EAAE,cAAc;AAC5B,IAAA,YAAY,EAAE,cAAc;AAC5B,IAAA,SAAS,EAAE,WAAW;AACtB,IAAA,aAAa,EAAE,eAAe;AAC9B,IAAA,aAAa,EAAE,eAAe;AAC9B,IAAA,YAAY,EAAE,cAAc;AAC5B,IAAA,aAAa,EAAE,eAAe;AAC9B,IAAA,UAAU,EAAE,YAAY;AACxB,IAAA,WAAW,EAAE,wBAAwB;AACrC,IAAA,gBAAgB,EAAE,kCAAkC;CACrD;AAED;;;;;;;;;;;;;;;AAeG;MACU,iBAAiB,GAAG,CAC/B,SAAiB,EACjB,OAA0B,KACf;IACX,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa;AAAE,QAAA,OAAO,IAAI;IAC1D,MAAM,IAAI,GACR,MAAM,CAAC,IAAI,CAAC,UAAU,CACvB,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/B,IAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5B,IAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,gBAAgB,GAAG,gBAAgB;AACvE,IAAA,IAAI,OAAe;AACnB,IAAA,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,OAAO;YACL,CAAA,gBAAA,EAAmB,SAAS,CAAA,QAAA,EAAW,KAAK,CAAA,uBAAA,CAAyB;AACrE,gBAAA,CAAA,8CAAA,EAAiD,SAAS,CAAA,CAAA,CAAG;AAC7D,gBAAA,CAAA,eAAA,EAAkB,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA,WAAA,CAAa;AAC9D,gBAAA,CAAA,cAAA,CAAgB;IACpB;SAAO;AACL,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,UAAU,GACd,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,YAAY;YAC7C,CAAC,OAAO,CAAC,QAAQ;YACjB,OAAO,CAAC,YAAY,KAAK,SAAS;YAClC,OAAO,CAAC,mBAAmB;QAC7B,IAAI,UAAU,EAAE;YACd,KAAK,CAAC,IAAI,CACR,CAAA,cAAA,EAAiB,OAAO,CAAC,mBAAmB,CAAA,oBAAA,CAAsB,CACnE;QACH;QACA,OAAO;YACL,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAA,EAAI,KAAK,CAAA,6BAAA,CAA+B;AACpE,gBAAA,CAAA,4BAAA,EAA+B,SAAS,CAAA,oBAAA,CAAsB;AAC9D,gBAAA,CAAA,EAAG,MAAM,CAAC,KAAK,CAAC,6BAA6B;IACjD;;;;AAIA,IAAA,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;AAC1B,IAAA,OAAO,KAAK;AACd;AAEA,MAAM,mBAAmB,GAAG,aAAa,CAAqB,SAAS,CAAC;AAExE;;;;;;;;;;;;AAYG;AACI,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,mBAAmB;AAEnE;AACO,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAExD,MAAM,0BAA0B,GAAG,aAAa,CAAqB,SAAS,CAAC;AAE/E;;;;;;;AAOG;AACI,MAAM,sBAAsB,GAAG,MACpC,UAAU,CAAC,0BAA0B;AAEvC;AACO,MAAM,2BAA2B,GAAG,0BAA0B,CAAC;AAUtE,MAAM,oBAAoB,GAAG,aAAa,CAAgB,EAAE,CAAC;AAE7D;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,oBAAoB;AAErE;AACO,MAAM,qBAAqB,GAAG,oBAAoB,CAAC;AAQ1D,MAAM,0BAA0B,GAAG,aAAa,CAE9C,SAAS,CAAC;AAEZ;;;;;;;;;;;;;;AAcG;AACI,MAAM,sBAAsB,GAAG,CAAC,QAAiB,KAAU;AAChE,IAAA,MAAM,MAAM,GAAG,UAAU,CAAC,0BAA0B,CAAC;IACrD,qBAAqB,CACnB,OAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,SAAS,CAAC,EACzC,CAAC,MAAM,EAAE,QAAQ,CAAC,CACnB;AACH;AAEA;AACO,MAAM,2BAA2B,GAAG,0BAA0B,CAAC;AAEtE;;;;;;;AAOG;AACI,MAAM,mBAAmB,GAAG,CACjC,EAAsB,EACtB,QAAQ,GAAG,IAAI,KACO;AACtB,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,IAAA,MAAM,MAAM,GAAG,EAAE,KAAK,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAC;IAC1D,sBAAsB,CAAC,YAAY,KAAK,SAAS,IAAI,MAAM,KAAK,YAAY,CAAC;AAC7E,IAAA,OAAO,MAAM;AACf;AA6BA,MAAM,aAAa,GAAG,aAAa,CACjC,SAAS,CACV;AACD,MAAM,iBAAiB,GAAG,aAAa,CAErC,SAAS,CAAC;AAEZ;;;AAGG;AACI,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,aAAa;AAE5D;;;AAGG;AACI,MAAM,kBAAkB,GAAG,MAAM,UAAU,CAAC,iBAAiB;AAepE;AACO,MAAM,cAAc,GAAG,aAAa,CAAC;AAE5C;AACO,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
5
5
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
6
|
-
import {
|
|
6
|
+
import { useFieldLabelTarget } from './FormContext.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Bulma Input component with full Bulma helper class support.
|
|
@@ -18,7 +18,9 @@ const InputBase = forwardRef(({ color, size, isRounded, isStatic, isHovered, isF
|
|
|
18
18
|
color,
|
|
19
19
|
...props,
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
// A labeled Field's generated id when no user id arrived (rest.id may be
|
|
22
|
+
// an undefined own key), reported to that Field (#1004).
|
|
23
|
+
const id = useFieldLabelTarget(rest.id);
|
|
22
24
|
const mainClass = usePrefixedClassNames('input', {
|
|
23
25
|
[`is-${color}`]: !!color,
|
|
24
26
|
[`is-${size}`]: !!size,
|
|
@@ -30,9 +32,8 @@ const InputBase = forwardRef(({ color, size, isRounded, isStatic, isHovered, isF
|
|
|
30
32
|
});
|
|
31
33
|
const inputClass = classNames(mainClass, bulmaHelperClasses, className);
|
|
32
34
|
return (jsx("input", { ref: ref, className: inputClass, disabled: disabled, readOnly: readOnly, ...rest,
|
|
33
|
-
// After the spread
|
|
34
|
-
|
|
35
|
-
id: rest.id ?? fieldLabelId }));
|
|
35
|
+
// After the spread, which may carry an undefined id key.
|
|
36
|
+
id: id }));
|
|
36
37
|
});
|
|
37
38
|
InputBase.displayName = 'InputBase';
|
|
38
39
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputBase.js","sources":["../../../src/form/InputBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {
|
|
1
|
+
{"version":3,"file":"InputBase.js","sources":["../../../src/form/InputBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useFieldLabelTarget } from './FormContext';\n\n/**\n * Props for the Input component.\n */\nexport interface InputBaseProps\n extends\n Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>,\n Omit<BulmaClassesProps, 'color'> {\n /** Bulma color modifier for the input. */\n color?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'black'\n | 'dark'\n | 'light'\n | 'white';\n /** Size modifier for the input. */\n size?: 'small' | 'medium' | 'large';\n /** Rounded input corners. */\n isRounded?: boolean;\n /** Styles the input as static text. It stays editable; add `readOnly` to stop edits. */\n isStatic?: boolean;\n /** Applies hovered state. */\n isHovered?: boolean;\n /** Applies focused state. */\n isFocused?: boolean;\n /**\n * Adds the `is-loading` class to the `<input>`. Bulma draws no spinner for it there: the\n * spinner belongs to the wrapping `Control`, so set `isLoading` on that `Control`.\n */\n isLoading?: boolean;\n /** Additional CSS classes to apply. */\n className?: string;\n /** Disabled input. */\n disabled?: boolean;\n /** Read-only input. */\n readOnly?: boolean;\n}\n\n/**\n * Bulma Input component with full Bulma helper class support.\n *\n * @function\n * @param {InputBaseProps} props - Props for the Input component.\n * @returns {JSX.Element} The rendered input element.\n * @see {@link https://bulma.io/documentation/form/input/ | Bulma Input documentation}\n */\nexport const InputBase = forwardRef<HTMLInputElement, InputBaseProps>(\n (\n {\n color,\n size,\n isRounded,\n isStatic,\n isHovered,\n isFocused,\n isLoading,\n className,\n disabled,\n readOnly,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color,\n ...props,\n });\n // A labeled Field's generated id when no user id arrived (rest.id may be\n // an undefined own key), reported to that Field (#1004).\n const id = useFieldLabelTarget(rest.id);\n\n const mainClass = usePrefixedClassNames('input', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-static': isStatic,\n 'is-hovered': isHovered,\n 'is-focused': isFocused,\n 'is-loading': isLoading,\n });\n const inputClass = classNames(mainClass, bulmaHelperClasses, className);\n\n return (\n <input\n ref={ref}\n className={inputClass}\n disabled={disabled}\n readOnly={readOnly}\n {...rest}\n // After the spread, which may carry an undefined id key.\n id={id}\n />\n );\n }\n);\nInputBase.displayName = 'InputBase';\n\nexport default InputBase;\n"],"names":["_jsx"],"mappings":";;;;;;;AA+CA;;;;;;;AAOG;AACI,MAAM,SAAS,GAAG,UAAU,CACjC,CACE,EACE,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;QACnD,KAAK;AACL,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;;;IAGF,MAAM,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;AAEvC,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE;AAC/C,QAAA,CAAC,MAAM,KAAK,CAAA,CAAE,GAAG,CAAC,CAAC,KAAK;AACxB,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACtB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,WAAW,EAAE,QAAQ;AACrB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA,CAAC;IACF,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;AAEvE,IAAA,QACEA,GAAA,CAAA,OAAA,EAAA,EACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,KACd,IAAI;;AAER,QAAA,EAAE,EAAE,EAAE,EAAA,CACN;AAEN,CAAC;AAEH,SAAS,CAAC,WAAW,GAAG,WAAW;;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
5
5
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
6
|
-
import {
|
|
6
|
+
import { useFieldLabelTarget } from './FormContext.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Bulma Select component with full Bulma helper class support.
|
|
@@ -18,7 +18,9 @@ const SelectBase = forwardRef(({ color, size, isRounded, isLoading, isActive, is
|
|
|
18
18
|
color,
|
|
19
19
|
...props,
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
// A labeled Field's generated id when no user id arrived (rest.id may be
|
|
22
|
+
// an undefined own key), reported to that Field (#1004).
|
|
23
|
+
const id = useFieldLabelTarget(rest.id);
|
|
22
24
|
const mainClass = usePrefixedClassNames('select', {
|
|
23
25
|
[`is-${color}`]: !!color,
|
|
24
26
|
[`is-${size}`]: !!size,
|
|
@@ -44,9 +46,9 @@ const SelectBase = forwardRef(({ color, size, isRounded, isLoading, isActive, is
|
|
|
44
46
|
selectProps.size = multipleSize;
|
|
45
47
|
}
|
|
46
48
|
return (jsx("div", { className: selectClass, children: jsx("select", { ref: ref, className: innerSelectClass || undefined, ...selectProps,
|
|
47
|
-
// After the spread
|
|
48
|
-
//
|
|
49
|
-
id:
|
|
49
|
+
// After the spread, which may carry an undefined id key; the id
|
|
50
|
+
// belongs on the inner <select>.
|
|
51
|
+
id: id, children: children }) }));
|
|
50
52
|
});
|
|
51
53
|
SelectBase.displayName = 'SelectBase';
|
|
52
54
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectBase.js","sources":["../../../src/form/SelectBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {
|
|
1
|
+
{"version":3,"file":"SelectBase.js","sources":["../../../src/form/SelectBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useFieldLabelTarget } from './FormContext';\n\n/**\n * Props for the Select component.\n */\nexport interface SelectBaseProps\n extends\n Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'>,\n Omit<BulmaClassesProps, 'color'> {\n /** Bulma color modifier for the select. */\n color?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'black'\n | 'dark'\n | 'light'\n | 'white';\n /** Size modifier for the select. */\n size?: 'small' | 'medium' | 'large';\n /** Rounded select corners. */\n isRounded?: boolean;\n /**\n * Replaces the chevron with a loading spinner.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n isLoading?: boolean;\n /** Applies Bulma's is-active modifier. */\n isActive?: boolean;\n /** Forces hovered state on the inner select. */\n isHovered?: boolean;\n /** Forces focused state on the inner select. */\n isFocused?: boolean;\n /** Makes the select span the full width of parent. */\n isFullwidth?: boolean;\n /** Makes the select span the full width of parent. @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n isFullWidth?: boolean;\n /** Additional CSS classes to apply. */\n className?: string;\n /** Disables the select. */\n disabled?: boolean;\n /** Allows multiple selections. */\n multiple?: boolean;\n /** Number of visible options in multiselect. */\n multipleSize?: number;\n /** `<option>` elements. */\n children?: React.ReactNode;\n}\n\n/**\n * Bulma Select component with full Bulma helper class support.\n *\n * @function\n * @param {SelectBaseProps} props - Props for the SelectBase component.\n * @returns {JSX.Element} The rendered select element.\n * @see {@link https://bulma.io/documentation/form/select/ | Bulma Select documentation}\n */\nexport const SelectBase = forwardRef<HTMLSelectElement, SelectBaseProps>(\n (\n {\n color,\n size,\n isRounded,\n isLoading,\n isActive,\n isHovered,\n isFocused,\n isFullwidth,\n isFullWidth,\n className,\n disabled,\n children,\n multiple,\n multipleSize,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color,\n ...props,\n });\n // A labeled Field's generated id when no user id arrived (rest.id may be\n // an undefined own key), reported to that Field (#1004).\n const id = useFieldLabelTarget(rest.id);\n\n const mainClass = usePrefixedClassNames('select', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-loading': isLoading,\n 'is-active': isActive,\n 'is-multiple': !!multiple,\n 'is-fullwidth': isFullwidth ?? isFullWidth,\n });\n const selectClass = classNames(mainClass, bulmaHelperClasses, className);\n\n // is-hovered / is-focused belong on the inner <select> element, not the wrapper.\n const innerSelectClass = usePrefixedClassNames('', {\n 'is-hovered': isHovered,\n 'is-focused': isFocused,\n });\n\n // Only set size attribute when multiple is true and multipleSize is specified\n const selectProps: React.SelectHTMLAttributes<HTMLSelectElement> = {\n disabled,\n multiple,\n ...rest,\n };\n\n if (multiple && typeof multipleSize === 'number') {\n selectProps.size = multipleSize;\n }\n\n return (\n <div className={selectClass}>\n <select\n ref={ref}\n className={innerSelectClass || undefined}\n {...selectProps}\n // After the spread, which may carry an undefined id key; the id\n // belongs on the inner <select>.\n id={id}\n >\n {children}\n </select>\n </div>\n );\n }\n);\n\nSelectBase.displayName = 'SelectBase';\n\nexport default SelectBase;\n"],"names":["_jsx"],"mappings":";;;;;;;AAwDA;;;;;;;AAOG;AACI,MAAM,UAAU,GAAG,UAAU,CAClC,CACE,EACE,KAAK,EACL,IAAI,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;QACnD,KAAK;AACL,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;;;IAGF,MAAM,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;AAEvC,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,EAAE;AAChD,QAAA,CAAC,MAAM,KAAK,CAAA,CAAE,GAAG,CAAC,CAAC,KAAK;AACxB,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACtB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,WAAW,EAAE,QAAQ;QACrB,aAAa,EAAE,CAAC,CAAC,QAAQ;QACzB,cAAc,EAAE,WAAW,IAAI,WAAW;AAC3C,KAAA,CAAC;IACF,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;;AAGxE,IAAA,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,EAAE,EAAE;AACjD,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA,CAAC;;AAGF,IAAA,MAAM,WAAW,GAAkD;QACjE,QAAQ;QACR,QAAQ;AACR,QAAA,GAAG,IAAI;KACR;AAED,IAAA,IAAI,QAAQ,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;AAChD,QAAA,WAAW,CAAC,IAAI,GAAG,YAAY;IACjC;AAEA,IAAA,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,WAAW,YACzBA,GAAA,CAAA,QAAA,EAAA,EACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,gBAAgB,IAAI,SAAS,KACpC,WAAW;;;AAGf,YAAA,EAAE,EAAE,EAAE,EAAA,QAAA,EAEL,QAAQ,EAAA,CACF,EAAA,CACL;AAEV,CAAC;AAGH,UAAU,CAAC,WAAW,GAAG,YAAY;;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
5
5
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
6
|
-
import {
|
|
6
|
+
import { useFieldLabelTarget } from './FormContext.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Bulma TextArea component with full Bulma helper class support.
|
|
@@ -18,7 +18,9 @@ const TextAreaBase = forwardRef(({ color, size, isRounded, isStatic, isHovered,
|
|
|
18
18
|
color,
|
|
19
19
|
...props,
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
// A labeled Field's generated id when no user id arrived (rest.id may be
|
|
22
|
+
// an undefined own key), reported to that Field (#1004).
|
|
23
|
+
const id = useFieldLabelTarget(rest.id);
|
|
22
24
|
// Note: `is-loading` is intentionally NOT applied to the <textarea> itself —
|
|
23
25
|
// Bulma documents `<div class="control is-loading">` as the loading pattern
|
|
24
26
|
// for textareas, not `<textarea class="textarea is-loading">`. The convenience
|
|
@@ -35,9 +37,8 @@ const TextAreaBase = forwardRef(({ color, size, isRounded, isStatic, isHovered,
|
|
|
35
37
|
});
|
|
36
38
|
const textareaClass = classNames(mainClass, bulmaHelperClasses, className);
|
|
37
39
|
return (jsx("textarea", { ref: ref, className: textareaClass, disabled: disabled, readOnly: readOnly, rows: rows, ...rest,
|
|
38
|
-
// After the spread
|
|
39
|
-
|
|
40
|
-
id: rest.id ?? fieldLabelId }));
|
|
40
|
+
// After the spread, which may carry an undefined id key.
|
|
41
|
+
id: id }));
|
|
41
42
|
});
|
|
42
43
|
TextAreaBase.displayName = 'TextAreaBase';
|
|
43
44
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextAreaBase.js","sources":["../../../src/form/TextAreaBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {
|
|
1
|
+
{"version":3,"file":"TextAreaBase.js","sources":["../../../src/form/TextAreaBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useFieldLabelTarget } from './FormContext';\n\n/**\n * Props for the TextArea component.\n */\nexport interface TextAreaBaseProps\n extends\n Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'>,\n Omit<BulmaClassesProps, 'color'> {\n /** Bulma color modifier for the textarea. */\n color?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'black'\n | 'dark'\n | 'light'\n | 'white';\n /** Size modifier for the textarea. */\n size?: 'small' | 'medium' | 'large';\n /**\n * Adds the `is-rounded` class to the `<textarea>`. Bulma styles it on `.input` only, so the\n * textarea's corners don't change.\n */\n isRounded?: boolean;\n /**\n * Adds the `is-static` class to the `<textarea>`. Bulma styles it on `.input` only, so the\n * textarea keeps its border, background and padding.\n */\n isStatic?: boolean;\n /** Applies hovered state. */\n isHovered?: boolean;\n /** Applies focused state. */\n isFocused?: boolean;\n /**\n * Accepted and ignored: `TextAreaBase` renders no loading state. The spinner belongs to the\n * wrapping `Control`, so set `isLoading` on that `Control`.\n */\n isLoading?: boolean;\n /** Applies Bulma's is-active modifier. */\n isActive?: boolean;\n /** Fixed textarea size (no resize). */\n hasFixedSize?: boolean;\n /** Additional CSS classes to apply. */\n className?: string;\n /** Disables the textarea. */\n disabled?: boolean;\n /** Read-only textarea. */\n readOnly?: boolean;\n /** Number of visible text lines. */\n rows?: number;\n}\n\n/**\n * Bulma TextArea component with full Bulma helper class support.\n *\n * @function\n * @param {TextAreaBaseProps} props - Props for the TextAreaBase component.\n * @returns {JSX.Element} The rendered textarea element.\n * @see {@link https://bulma.io/documentation/form/textarea/ | Bulma Textarea documentation}\n */\nexport const TextAreaBase = forwardRef<HTMLTextAreaElement, TextAreaBaseProps>(\n (\n {\n color,\n size,\n isRounded,\n isStatic,\n isHovered,\n isFocused,\n isLoading: _isLoading,\n isActive,\n hasFixedSize,\n className,\n disabled,\n readOnly,\n rows,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color,\n ...props,\n });\n // A labeled Field's generated id when no user id arrived (rest.id may be\n // an undefined own key), reported to that Field (#1004).\n const id = useFieldLabelTarget(rest.id);\n\n // Note: `is-loading` is intentionally NOT applied to the <textarea> itself —\n // Bulma documents `<div class=\"control is-loading\">` as the loading pattern\n // for textareas, not `<textarea class=\"textarea is-loading\">`. The convenience\n // <TextArea> component routes its `isLoading` prop to the wrapping Control.\n const mainClass = usePrefixedClassNames('textarea', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-static': isStatic,\n 'is-hovered': isHovered,\n 'is-focused': isFocused,\n 'is-active': isActive,\n 'has-fixed-size': hasFixedSize,\n });\n const textareaClass = classNames(mainClass, bulmaHelperClasses, className);\n\n return (\n <textarea\n ref={ref}\n className={textareaClass}\n disabled={disabled}\n readOnly={readOnly}\n rows={rows}\n {...rest}\n // After the spread, which may carry an undefined id key.\n id={id}\n />\n );\n }\n);\nTextAreaBase.displayName = 'TextAreaBase';\n\nexport default TextAreaBase;\n"],"names":["_jsx"],"mappings":";;;;;;;AA2DA;;;;;;;AAOG;AACI,MAAM,YAAY,GAAG,UAAU,CACpC,CACE,EACE,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EAAE,UAAU,EACrB,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;QACnD,KAAK;AACL,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;;;IAGF,MAAM,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;;;;;AAMvC,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,UAAU,EAAE;AAClD,QAAA,CAAC,MAAM,KAAK,CAAA,CAAE,GAAG,CAAC,CAAC,KAAK;AACxB,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACtB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,WAAW,EAAE,QAAQ;AACrB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,WAAW,EAAE,QAAQ;AACrB,QAAA,gBAAgB,EAAE,YAAY;AAC/B,KAAA,CAAC;IACF,MAAM,aAAa,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;IAE1E,QACEA,kBACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,aAAa,EACxB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EAAA,GACN,IAAI;;AAER,QAAA,EAAE,EAAE,EAAE,EAAA,CACN;AAEN,CAAC;AAEH,YAAY,CAAC,WAAW,GAAG,cAAc;;"}
|
|
@@ -11,7 +11,7 @@ import { PickerPopover } from './_pickerInternals/PickerPopover.js';
|
|
|
11
11
|
import { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker.js';
|
|
12
12
|
import { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry.js';
|
|
13
13
|
import { useControlLoading } from './controlLoading.js';
|
|
14
|
-
import {
|
|
14
|
+
import { useFieldLabelTarget } from './FormContext.js';
|
|
15
15
|
import { Icon } from '../elements/Icon.js';
|
|
16
16
|
import { Buttons } from '../elements/Buttons.js';
|
|
17
17
|
|
|
@@ -46,8 +46,7 @@ const TimeInputBase = forwardRef((props, ref) => {
|
|
|
46
46
|
// when the caller set none, as InputBase does, and the popover's ids
|
|
47
47
|
// follow it. Inline there is no input to name, so nothing takes the
|
|
48
48
|
// Field's id or builds on it.
|
|
49
|
-
const
|
|
50
|
-
const id = idProp ?? (inline ? undefined : fieldLabelId);
|
|
49
|
+
const id = useFieldLabelTarget(idProp, !inline);
|
|
51
50
|
// The launcher gives way to the loading spinner of a Control this sits in.
|
|
52
51
|
const controlLoading = useControlLoading();
|
|
53
52
|
const triggerIcon = triggerIconProp ?? !controlLoading;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeInputBase.js","sources":["../../../src/form/TimeInputBase.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 PickerPosition,\n HourFormat,\n PickerLabels,\n mergeLabels,\n} from './_pickerInternals/pickerTypes';\nimport {\n formatTime,\n hourCycleFromFormat,\n parseTime,\n DateFormatOption,\n DEFAULT_TIME_FORMAT_24,\n DEFAULT_TIME_FORMAT_12,\n} from './_pickerInternals/formatters';\nimport {\n setTimeOfDay,\n floorMin,\n isWithin,\n snapTimeToIncrement,\n} from './_pickerInternals/dateUtils';\nimport { TimeWheels } from './_pickerInternals/TimeWheels';\nimport { PickerPopover } from './_pickerInternals/PickerPopover';\nimport { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker';\nimport { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry';\nimport { useControlLoading } from './controlLoading';\nimport { useFieldLabelId } from './FormContext';\nimport { Icon } from '../elements/Icon';\nimport { Buttons } from '../elements/Buttons';\n\nconst toIsoTime = (d: Date, withSeconds: boolean): string => {\n const hh = String(d.getHours()).padStart(2, '0');\n const mm = String(d.getMinutes()).padStart(2, '0');\n if (!withSeconds) return `${hh}:${mm}`;\n const ss = String(d.getSeconds()).padStart(2, '0');\n return `${hh}:${mm}:${ss}`;\n};\n\nconst fromIsoTime = (s: string): Date | null => {\n // The HTML time value may carry fractional seconds (the spec allows them\n // and some engines normalize to `:ss.sss`); accept and drop.\n const m = /^(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d{1,3})?)?$/.exec(s);\n if (!m) return null;\n const today = new Date();\n return new Date(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n Number(m[1]),\n Number(m[2]),\n m[3] ? Number(m[3]) : 0,\n 0\n );\n};\n\n/**\n * Props for the raw TimeInput base. Use the higher-level `TimeInput` for\n * Field/Control composition; `TimeInputBase` is the input + popover only.\n */\nexport interface TimeInputBaseProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'value'\n | 'defaultValue'\n | 'onChange'\n | 'size'\n | 'color'\n | 'min'\n | 'max'\n | 'type'\n | 'popover'\n >,\n Omit<BulmaClassesProps, 'color'> {\n /** Controlled selected time (date portion is preserved). */\n value?: Date | null;\n /** Initial value for uncontrolled usage. */\n defaultValue?: Date | null;\n /** Fired when the value changes. */\n onChange?: (d: Date | null) => void;\n /** Fired when the popover opens. */\n onOpen?: () => void;\n /** Fired when the popover closes. */\n onClose?: () => void;\n /**\n * Earliest selectable time. A `min` before year 1 is raised to midnight on\n * 1 January of year 1, and a `value` dated before then is out of range, so\n * the wheels and typing change nothing on it, as in the date pickers.\n */\n min?: Date;\n /** Latest selectable time. */\n max?: Date;\n /** Disable the input. */\n disabled?: boolean;\n /** Make the input read-only. */\n readOnly?: boolean;\n /** Placeholder text for the input. */\n placeholder?: string;\n /**\n * Token format string or `Intl.DateTimeFormat` options.\n * @defaultValue (see below)\n */\n format?: DateFormatOption;\n /**\n * Custom parser. Enter and leaving the field call it only if the user\n * changed the text, so focus passing through commits nothing and the value\n * keeps what the format leaves out, such as seconds and the date.\n */\n parse?: (s: string) => Date | null;\n /** BCP-47 locale tag for Intl formatting. */\n locale?: string;\n /** Render the spinner inline (no popover). */\n inline?: boolean;\n /** Use `<input type=\"time\">` on coarse-pointer + small-viewport devices. */\n mobileNative?: boolean | 'auto';\n /** Allow segmented keyboard typing in the input (type the time directly, auto-advancing across segments). `false` makes the field picker-only. */\n editable?: boolean;\n /** Whether the spinner popover exists. `false` makes the field input-only (segmented typing, no popover). */\n popover?: boolean;\n /**\n * Open the popover when the input is focused. Focus that a closing popover\n * hands back to the input leaves it closed. Dismissing it commits nothing:\n * an empty field stays empty, and leaving afterwards commits only what was\n * typed since. With it off, the launcher or Alt+ArrowDown opens it.\n */\n openOnFocus?: boolean;\n /** Close the popover after a time is selected (off by default). */\n closeOnSelect?: boolean;\n /** Popover anchor position relative to the input. */\n position?: PickerPosition;\n /**\n * Render the popover into `document.body` via portal. On a narrow screen\n * an in-place popover spans the bottom of the viewport, while a portaled\n * one stays on its `position` corner.\n */\n appendToBody?: boolean;\n /**\n * Bulma color modifier for the input, also carried by the wheels, where it\n * colors the selection band. A focused wheel's keyboard focus ring is drawn\n * inside the band in the color's `-invert`, like the selected value, so it\n * shows on the fill. Unset, the wheels use\n * `--bulma-timeinput-wheel-selected-bg`, which defaults to `primary`.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Render the input with rounded corners. */\n isRounded?: boolean;\n /** Hour format. `'12'` shows an AM/PM toggle. */\n hourFormat?: HourFormat;\n /** Show a seconds column. Note: iOS Safari's native time picker UI does not include a seconds wheel; pass `mobileNative={false}` if you need one on iOS. */\n enableSeconds?: boolean;\n /** Hour step for the spinner. */\n incrementHours?: number;\n /** Minute step. Combine with `min`/`max` for slot-style pickers. */\n incrementMinutes?: number;\n /** Second step. Default `1`. */\n incrementSeconds?: number;\n /** Predicate returning `true` for times that should be skipped. Blocked times are also rejected during manual typing. */\n unselectableTimes?: (d: Date) => 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 /** Optional translatable string overrides. */\n labels?: PickerLabels;\n /** Play a short audible click on each wheel-item crossing. Substitute for haptic feedback on iOS Safari (which has no web haptic API as of May 2026); on Android, `navigator.vibrate(5)` fires automatically regardless. */\n audioTick?: boolean;\n /** Auto-route platform-appropriate feedback: vibrate on Android (already happening), audio thunk on iOS (where vibrate is unavailable). One switch instead of platform-sniffing on the consumer side. `audioTick={true}` always wins. */\n haptics?: boolean;\n}\n\n/**\n * Raw TimeInput — input + popover spinner without Field/Control wrapping.\n * Use `TimeInput` for the convenience wrapper.\n *\n * @function\n * @param {TimeInputBaseProps} props\n * @returns {JSX.Element}\n */\nexport const TimeInputBase = forwardRef<HTMLInputElement, TimeInputBaseProps>(\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 = false,\n position = 'bottom-left',\n appendToBody = false,\n color,\n size,\n isRounded,\n hourFormat = '24',\n enableSeconds = false,\n incrementHours = 1,\n incrementMinutes = 1,\n incrementSeconds = 1,\n unselectableTimes,\n className,\n name,\n form,\n required,\n id: idProp,\n onFocus,\n onClick,\n onKeyDown,\n onBlur,\n iconLeftName: _iconLeftName,\n triggerIcon: triggerIconProp,\n triggerIconName = 'chevron-down',\n labels,\n audioTick = false,\n haptics = false,\n ...rest\n } = props;\n // Inside a labeled Field the input takes the id the label points at\n // when the caller set none, as InputBase does, and the popover's ids\n // follow it. Inline there is no input to name, so nothing takes the\n // Field's id or builds on it.\n const fieldLabelId = useFieldLabelId();\n const id = idProp ?? (inline ? undefined : fieldLabelId);\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 // Platform-appropriate feedback routing: when `haptics` is opted in and\n // the runtime has no Vibration API (notably iOS Safari), enable the\n // audio thunk so the user still gets *some* tactile cue. When vibrate\n // is available (Android Chrome etc.), the existing unconditional\n // `navigator.vibrate(5)` carries the haptic — no audio added unless\n // the consumer explicitly set `audioTick`. `audioTick` always wins.\n const hasVibrate =\n typeof navigator !== 'undefined' &&\n typeof navigator.vibrate === 'function';\n const effectiveAudioTick = audioTick || (haptics && !hasVibrate);\n const t = mergeLabels(labels);\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<Date | null>(\n defaultValue ?? null\n );\n const value = isControlled ? (controlledValue ?? null) : internalValue;\n\n const defaultFormat: DateFormatOption =\n format ??\n (hourFormat === '12'\n ? enableSeconds\n ? 'hh:mm:ss A'\n : DEFAULT_TIME_FORMAT_12\n : enableSeconds\n ? 'HH:mm:ss'\n : DEFAULT_TIME_FORMAT_24);\n\n // The displayed format is the source of truth for the hour cycle: an\n // explicit 12-hour `format` must drive a 12-hour wheel even when\n // `hourFormat` was left at its default. Fall back to the raw prop only when\n // the cycle can't be read from the format (an Intl-options object, or no\n // hour token).\n const effectiveHourFormat =\n hourCycleFromFormat(defaultFormat) ?? hourFormat;\n\n const [open, setOpenState] = useState(false);\n const [text, setText] = useState<string>(\n value ? formatTime(value, defaultFormat, locale) : ''\n );\n\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n // Snapshot of value at the moment the popover opens, used by Cancel.\n const valueAtOpenRef = useRef<Date | null>(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, isSmallViewport } = useNativeMobilePicker({\n force: mobileNative === 'auto' ? undefined : mobileNative,\n });\n const useNative = !inline && shouldUseNative;\n const wheelItemHeight = isSmallViewport ? 40 : 32;\n\n const inputClass = usePrefixedClassNames('input', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n });\n const containerClass = usePrefixedClassNames('timeinput-container');\n const triggerClass = usePrefixedClassNames('timeinput-trigger');\n const panelClass = usePrefixedClassNames('timeinput-panel');\n const footerClass = usePrefixedClassNames('timeinput-footer');\n const footerButton = usePrefixedClassNames('button', 'is-small');\n const footerOkClass = usePrefixedClassNames(\n 'button',\n 'is-small',\n 'timeinput-footer-ok'\n );\n const mobileFooterClass = usePrefixedClassNames('timeinput-footer-mobile');\n const mobileFooterResetClass = usePrefixedClassNames(\n 'timeinput-footer-reset'\n );\n const mobileFooterDoneClass = usePrefixedClassNames(\n 'timeinput-footer-done'\n );\n\n // What the latest request asked for, so a second request in the same\n // event sees it before React renders. The callbacks fire here rather than\n // in a state updater, which StrictMode calls twice, and after the state\n // is set, so a request a callback makes is the one that lands last.\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) {\n valueAtOpenRef.current = value;\n onOpen?.();\n } else {\n onClose?.();\n }\n },\n [onOpen, onClose, value]\n );\n\n useEffect(() => {\n setText(value ? formatTime(value, defaultFormat, locale) : '');\n }, [value, defaultFormat, locale]);\n\n // A value's date before year 1 is out of range, as in the date pickers.\n const lowerBound = useMemo(() => floorMin(min), [min]);\n\n const commitValue = useCallback(\n (next: Date | null) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n\n // An empty field starts from today, at the whole minute or second the\n // wheels show.\n const handleSpinnerChange = useCallback(\n (parts: { hours: number; minutes: number; seconds?: number }) => {\n const next = value\n ? setTimeOfDay(value, parts)\n : setTimeOfDay(new Date(), {\n ...parts,\n seconds: parts.seconds ?? 0,\n milliseconds: 0,\n });\n if (!isWithin(next, lowerBound, max)) return;\n commitValue(next);\n },\n [value, lowerBound, max, commitValue]\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 : parseTime(\n trimmed,\n fmt ??\n (typeof defaultFormat === 'string'\n ? defaultFormat\n : DEFAULT_TIME_FORMAT_24)\n );\n },\n [parse, format, defaultFormat]\n );\n\n // The Date the user edits when starting without a current value. Noon so\n // the 12h / 24h hour calculations are unambiguous.\n const makeBaseDate = useCallback((): Date => {\n const d = new Date();\n d.setHours(12, 0, 0, 0);\n return d;\n }, []);\n\n const inputReadOnlyAttr = !!readOnly || !editable;\n const canOpen = !!popover && !disabled && !readOnly;\n\n const { inputHandlers } = useSegmentedEntry({\n format: defaultFormat,\n value,\n commitValue,\n formatFn: formatTime,\n tryParse,\n text,\n setText,\n makeBaseDate,\n locale,\n min: lowerBound,\n max,\n isBlocked: unselectableTimes,\n disabled,\n readOnly,\n editable,\n popover,\n openOnFocus,\n closeOnSelect,\n isOpen: open,\n setOpen,\n inputRef,\n containerRef,\n onFocus,\n onClick,\n onKeyDown,\n onBlur,\n });\n\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (inputRef 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 =\n node;\n },\n [ref]\n );\n\n if (useNative) {\n const nativeStep = enableSeconds\n ? incrementSeconds\n : incrementMinutes * 60;\n return (\n <input\n {...cleanRest}\n ref={combinedRef}\n type=\"time\"\n step={nativeStep}\n className={classNames(inputClass, bulmaHelperClasses, className)}\n value={value ? toIsoTime(value, enableSeconds) : ''}\n onChange={e => {\n const parsed = e.target.value ? fromIsoTime(e.target.value) : null;\n commitValue(parsed);\n }}\n min={min ? toIsoTime(min, enableSeconds) : undefined}\n max={max ? toIsoTime(max, enableSeconds) : undefined}\n disabled={disabled}\n readOnly={readOnly}\n placeholder={placeholder}\n name={name}\n form={form}\n required={required}\n id={id}\n />\n );\n }\n\n const spinnerValue = {\n hours: value?.getHours() ?? 0,\n minutes: value?.getMinutes() ?? 0,\n seconds: enableSeconds ? (value?.getSeconds() ?? 0) : undefined,\n };\n\n const panel = (\n <div className={panelClass}>\n <TimeWheels\n value={spinnerValue}\n onChange={handleSpinnerChange}\n hourFormat={effectiveHourFormat}\n enableSeconds={enableSeconds}\n incrementHours={incrementHours}\n incrementMinutes={incrementMinutes}\n incrementSeconds={incrementSeconds}\n unselectableTimes={unselectableTimes}\n color={color}\n size={size}\n disabled={disabled}\n // The popover panel takes `popoverId`, so the wheels inside it take\n // one of their own. Inline there is no panel, and the wheels keep\n // the id they released with.\n id={inline ? popoverId : `${popoverId}-time`}\n labels={labels}\n itemHeight={wheelItemHeight}\n audioTick={effectiveAudioTick}\n onCommit={() => setOpen(false)}\n />\n {/* Footer is popover-only. Desktop gets the OK / Now / Cancel triad;\n mobile drops to an iOS-style \"Reset / ✓\" pair to match the OS\n picker's footer affordances and free up vertical space on small\n screens. */}\n {!inline && !isSmallViewport && (\n <Buttons className={footerClass} hasAddons>\n <button\n type=\"button\"\n className={footerOkClass}\n onClick={() => setOpen(false)}\n >\n {t.ok}\n </button>\n <button\n type=\"button\"\n className={footerButton}\n onClick={() => {\n commitValue(\n snapTimeToIncrement(new Date(), {\n incrementHours,\n incrementMinutes,\n incrementSeconds,\n enableSeconds,\n })\n );\n setOpen(false);\n }}\n >\n {t.now}\n </button>\n <button\n type=\"button\"\n className={footerButton}\n onClick={() => {\n commitValue(valueAtOpenRef.current);\n setOpen(false);\n }}\n >\n {t.cancel}\n </button>\n </Buttons>\n )}\n {!inline && isSmallViewport && (\n <div className={mobileFooterClass}>\n <button\n type=\"button\"\n className={mobileFooterResetClass}\n onClick={() => {\n commitValue(valueAtOpenRef.current);\n setOpen(false);\n }}\n >\n {t.reset}\n </button>\n <button\n type=\"button\"\n className={mobileFooterDoneClass}\n aria-label={t.done}\n onClick={() => setOpen(false)}\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 22 22\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5 11l4 4 8-8\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n )}\n </div>\n );\n\n if (inline) {\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n className={classNames(containerClass, bulmaHelperClasses, className)}\n >\n {panel}\n {name && (\n <input\n type=\"hidden\"\n name={name}\n form={form}\n value={value ? toIsoTime(value, enableSeconds) : ''}\n required={required}\n />\n )}\n </div>\n );\n }\n\n return (\n <div\n ref={containerRef}\n className={classNames(containerClass, bulmaHelperClasses, className)}\n {...cleanRest}\n >\n <input\n ref={combinedRef}\n type=\"text\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={popoverId}\n autoComplete=\"off\"\n className={inputClass}\n value={text}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={inputReadOnlyAttr}\n name={name}\n form={form}\n required={required}\n id={id}\n {...inputHandlers}\n />\n {popover && triggerIcon && (\n <button\n type=\"button\"\n className={triggerClass}\n onClick={() => {\n if (canOpen) setOpen(!open);\n }}\n disabled={!canOpen}\n aria-label={t.chooseTime}\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={() => setOpen(false)}\n anchorRef={containerRef}\n position={position}\n appendToBody={appendToBody}\n ariaLabel={t.chooseTime}\n id={popoverId}\n restoreFocusRef={inputRef}\n >\n {panel}\n </PickerPopover>\n )}\n </div>\n );\n }\n);\n\nTimeInputBase.displayName = 'TimeInputBase';\n\nexport default TimeInputBase;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TimeInputBase.js","sources":["../../../src/form/TimeInputBase.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 PickerPosition,\n HourFormat,\n PickerLabels,\n mergeLabels,\n} from './_pickerInternals/pickerTypes';\nimport {\n formatTime,\n hourCycleFromFormat,\n parseTime,\n DateFormatOption,\n DEFAULT_TIME_FORMAT_24,\n DEFAULT_TIME_FORMAT_12,\n} from './_pickerInternals/formatters';\nimport {\n setTimeOfDay,\n floorMin,\n isWithin,\n snapTimeToIncrement,\n} from './_pickerInternals/dateUtils';\nimport { TimeWheels } from './_pickerInternals/TimeWheels';\nimport { PickerPopover } from './_pickerInternals/PickerPopover';\nimport { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker';\nimport { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry';\nimport { useControlLoading } from './controlLoading';\nimport { useFieldLabelTarget } from './FormContext';\nimport { Icon } from '../elements/Icon';\nimport { Buttons } from '../elements/Buttons';\n\nconst toIsoTime = (d: Date, withSeconds: boolean): string => {\n const hh = String(d.getHours()).padStart(2, '0');\n const mm = String(d.getMinutes()).padStart(2, '0');\n if (!withSeconds) return `${hh}:${mm}`;\n const ss = String(d.getSeconds()).padStart(2, '0');\n return `${hh}:${mm}:${ss}`;\n};\n\nconst fromIsoTime = (s: string): Date | null => {\n // The HTML time value may carry fractional seconds (the spec allows them\n // and some engines normalize to `:ss.sss`); accept and drop.\n const m = /^(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d{1,3})?)?$/.exec(s);\n if (!m) return null;\n const today = new Date();\n return new Date(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n Number(m[1]),\n Number(m[2]),\n m[3] ? Number(m[3]) : 0,\n 0\n );\n};\n\n/**\n * Props for the raw TimeInput base. Use the higher-level `TimeInput` for\n * Field/Control composition; `TimeInputBase` is the input + popover only.\n */\nexport interface TimeInputBaseProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'value'\n | 'defaultValue'\n | 'onChange'\n | 'size'\n | 'color'\n | 'min'\n | 'max'\n | 'type'\n | 'popover'\n >,\n Omit<BulmaClassesProps, 'color'> {\n /** Controlled selected time (date portion is preserved). */\n value?: Date | null;\n /** Initial value for uncontrolled usage. */\n defaultValue?: Date | null;\n /** Fired when the value changes. */\n onChange?: (d: Date | null) => void;\n /** Fired when the popover opens. */\n onOpen?: () => void;\n /** Fired when the popover closes. */\n onClose?: () => void;\n /**\n * Earliest selectable time. A `min` before year 1 is raised to midnight on\n * 1 January of year 1, and a `value` dated before then is out of range, so\n * the wheels and typing change nothing on it, as in the date pickers.\n */\n min?: Date;\n /** Latest selectable time. */\n max?: Date;\n /** Disable the input. */\n disabled?: boolean;\n /** Make the input read-only. */\n readOnly?: boolean;\n /** Placeholder text for the input. */\n placeholder?: string;\n /**\n * Token format string or `Intl.DateTimeFormat` options.\n * @defaultValue (see below)\n */\n format?: DateFormatOption;\n /**\n * Custom parser. Enter and leaving the field call it only if the user\n * changed the text, so focus passing through commits nothing and the value\n * keeps what the format leaves out, such as seconds and the date.\n */\n parse?: (s: string) => Date | null;\n /** BCP-47 locale tag for Intl formatting. */\n locale?: string;\n /** Render the spinner inline (no popover). */\n inline?: boolean;\n /** Use `<input type=\"time\">` on coarse-pointer + small-viewport devices. */\n mobileNative?: boolean | 'auto';\n /** Allow segmented keyboard typing in the input (type the time directly, auto-advancing across segments). `false` makes the field picker-only. */\n editable?: boolean;\n /** Whether the spinner popover exists. `false` makes the field input-only (segmented typing, no popover). */\n popover?: boolean;\n /**\n * Open the popover when the input is focused. Focus that a closing popover\n * hands back to the input leaves it closed. Dismissing it commits nothing:\n * an empty field stays empty, and leaving afterwards commits only what was\n * typed since. With it off, the launcher or Alt+ArrowDown opens it.\n */\n openOnFocus?: boolean;\n /** Close the popover after a time is selected (off by default). */\n closeOnSelect?: boolean;\n /** Popover anchor position relative to the input. */\n position?: PickerPosition;\n /**\n * Render the popover into `document.body` via portal. On a narrow screen\n * an in-place popover spans the bottom of the viewport, while a portaled\n * one stays on its `position` corner.\n */\n appendToBody?: boolean;\n /**\n * Bulma color modifier for the input, also carried by the wheels, where it\n * colors the selection band. A focused wheel's keyboard focus ring is drawn\n * inside the band in the color's `-invert`, like the selected value, so it\n * shows on the fill. Unset, the wheels use\n * `--bulma-timeinput-wheel-selected-bg`, which defaults to `primary`.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Render the input with rounded corners. */\n isRounded?: boolean;\n /** Hour format. `'12'` shows an AM/PM toggle. */\n hourFormat?: HourFormat;\n /** Show a seconds column. Note: iOS Safari's native time picker UI does not include a seconds wheel; pass `mobileNative={false}` if you need one on iOS. */\n enableSeconds?: boolean;\n /** Hour step for the spinner. */\n incrementHours?: number;\n /** Minute step. Combine with `min`/`max` for slot-style pickers. */\n incrementMinutes?: number;\n /** Second step. Default `1`. */\n incrementSeconds?: number;\n /** Predicate returning `true` for times that should be skipped. Blocked times are also rejected during manual typing. */\n unselectableTimes?: (d: Date) => 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 /** Optional translatable string overrides. */\n labels?: PickerLabels;\n /** Play a short audible click on each wheel-item crossing. Substitute for haptic feedback on iOS Safari (which has no web haptic API as of May 2026); on Android, `navigator.vibrate(5)` fires automatically regardless. */\n audioTick?: boolean;\n /** Auto-route platform-appropriate feedback: vibrate on Android (already happening), audio thunk on iOS (where vibrate is unavailable). One switch instead of platform-sniffing on the consumer side. `audioTick={true}` always wins. */\n haptics?: boolean;\n}\n\n/**\n * Raw TimeInput — input + popover spinner without Field/Control wrapping.\n * Use `TimeInput` for the convenience wrapper.\n *\n * @function\n * @param {TimeInputBaseProps} props\n * @returns {JSX.Element}\n */\nexport const TimeInputBase = forwardRef<HTMLInputElement, TimeInputBaseProps>(\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 = false,\n position = 'bottom-left',\n appendToBody = false,\n color,\n size,\n isRounded,\n hourFormat = '24',\n enableSeconds = false,\n incrementHours = 1,\n incrementMinutes = 1,\n incrementSeconds = 1,\n unselectableTimes,\n className,\n name,\n form,\n required,\n id: idProp,\n onFocus,\n onClick,\n onKeyDown,\n onBlur,\n iconLeftName: _iconLeftName,\n triggerIcon: triggerIconProp,\n triggerIconName = 'chevron-down',\n labels,\n audioTick = false,\n haptics = false,\n ...rest\n } = props;\n // Inside a labeled Field the input takes the id the label points at\n // when the caller set none, as InputBase does, and the popover's ids\n // follow it. Inline there is no input to name, so nothing takes the\n // Field's id or builds on it.\n const id = useFieldLabelTarget(idProp, !inline);\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 // Platform-appropriate feedback routing: when `haptics` is opted in and\n // the runtime has no Vibration API (notably iOS Safari), enable the\n // audio thunk so the user still gets *some* tactile cue. When vibrate\n // is available (Android Chrome etc.), the existing unconditional\n // `navigator.vibrate(5)` carries the haptic — no audio added unless\n // the consumer explicitly set `audioTick`. `audioTick` always wins.\n const hasVibrate =\n typeof navigator !== 'undefined' &&\n typeof navigator.vibrate === 'function';\n const effectiveAudioTick = audioTick || (haptics && !hasVibrate);\n const t = mergeLabels(labels);\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<Date | null>(\n defaultValue ?? null\n );\n const value = isControlled ? (controlledValue ?? null) : internalValue;\n\n const defaultFormat: DateFormatOption =\n format ??\n (hourFormat === '12'\n ? enableSeconds\n ? 'hh:mm:ss A'\n : DEFAULT_TIME_FORMAT_12\n : enableSeconds\n ? 'HH:mm:ss'\n : DEFAULT_TIME_FORMAT_24);\n\n // The displayed format is the source of truth for the hour cycle: an\n // explicit 12-hour `format` must drive a 12-hour wheel even when\n // `hourFormat` was left at its default. Fall back to the raw prop only when\n // the cycle can't be read from the format (an Intl-options object, or no\n // hour token).\n const effectiveHourFormat =\n hourCycleFromFormat(defaultFormat) ?? hourFormat;\n\n const [open, setOpenState] = useState(false);\n const [text, setText] = useState<string>(\n value ? formatTime(value, defaultFormat, locale) : ''\n );\n\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n // Snapshot of value at the moment the popover opens, used by Cancel.\n const valueAtOpenRef = useRef<Date | null>(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, isSmallViewport } = useNativeMobilePicker({\n force: mobileNative === 'auto' ? undefined : mobileNative,\n });\n const useNative = !inline && shouldUseNative;\n const wheelItemHeight = isSmallViewport ? 40 : 32;\n\n const inputClass = usePrefixedClassNames('input', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n });\n const containerClass = usePrefixedClassNames('timeinput-container');\n const triggerClass = usePrefixedClassNames('timeinput-trigger');\n const panelClass = usePrefixedClassNames('timeinput-panel');\n const footerClass = usePrefixedClassNames('timeinput-footer');\n const footerButton = usePrefixedClassNames('button', 'is-small');\n const footerOkClass = usePrefixedClassNames(\n 'button',\n 'is-small',\n 'timeinput-footer-ok'\n );\n const mobileFooterClass = usePrefixedClassNames('timeinput-footer-mobile');\n const mobileFooterResetClass = usePrefixedClassNames(\n 'timeinput-footer-reset'\n );\n const mobileFooterDoneClass = usePrefixedClassNames(\n 'timeinput-footer-done'\n );\n\n // What the latest request asked for, so a second request in the same\n // event sees it before React renders. The callbacks fire here rather than\n // in a state updater, which StrictMode calls twice, and after the state\n // is set, so a request a callback makes is the one that lands last.\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) {\n valueAtOpenRef.current = value;\n onOpen?.();\n } else {\n onClose?.();\n }\n },\n [onOpen, onClose, value]\n );\n\n useEffect(() => {\n setText(value ? formatTime(value, defaultFormat, locale) : '');\n }, [value, defaultFormat, locale]);\n\n // A value's date before year 1 is out of range, as in the date pickers.\n const lowerBound = useMemo(() => floorMin(min), [min]);\n\n const commitValue = useCallback(\n (next: Date | null) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n\n // An empty field starts from today, at the whole minute or second the\n // wheels show.\n const handleSpinnerChange = useCallback(\n (parts: { hours: number; minutes: number; seconds?: number }) => {\n const next = value\n ? setTimeOfDay(value, parts)\n : setTimeOfDay(new Date(), {\n ...parts,\n seconds: parts.seconds ?? 0,\n milliseconds: 0,\n });\n if (!isWithin(next, lowerBound, max)) return;\n commitValue(next);\n },\n [value, lowerBound, max, commitValue]\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 : parseTime(\n trimmed,\n fmt ??\n (typeof defaultFormat === 'string'\n ? defaultFormat\n : DEFAULT_TIME_FORMAT_24)\n );\n },\n [parse, format, defaultFormat]\n );\n\n // The Date the user edits when starting without a current value. Noon so\n // the 12h / 24h hour calculations are unambiguous.\n const makeBaseDate = useCallback((): Date => {\n const d = new Date();\n d.setHours(12, 0, 0, 0);\n return d;\n }, []);\n\n const inputReadOnlyAttr = !!readOnly || !editable;\n const canOpen = !!popover && !disabled && !readOnly;\n\n const { inputHandlers } = useSegmentedEntry({\n format: defaultFormat,\n value,\n commitValue,\n formatFn: formatTime,\n tryParse,\n text,\n setText,\n makeBaseDate,\n locale,\n min: lowerBound,\n max,\n isBlocked: unselectableTimes,\n disabled,\n readOnly,\n editable,\n popover,\n openOnFocus,\n closeOnSelect,\n isOpen: open,\n setOpen,\n inputRef,\n containerRef,\n onFocus,\n onClick,\n onKeyDown,\n onBlur,\n });\n\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (inputRef 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 =\n node;\n },\n [ref]\n );\n\n if (useNative) {\n const nativeStep = enableSeconds\n ? incrementSeconds\n : incrementMinutes * 60;\n return (\n <input\n {...cleanRest}\n ref={combinedRef}\n type=\"time\"\n step={nativeStep}\n className={classNames(inputClass, bulmaHelperClasses, className)}\n value={value ? toIsoTime(value, enableSeconds) : ''}\n onChange={e => {\n const parsed = e.target.value ? fromIsoTime(e.target.value) : null;\n commitValue(parsed);\n }}\n min={min ? toIsoTime(min, enableSeconds) : undefined}\n max={max ? toIsoTime(max, enableSeconds) : undefined}\n disabled={disabled}\n readOnly={readOnly}\n placeholder={placeholder}\n name={name}\n form={form}\n required={required}\n id={id}\n />\n );\n }\n\n const spinnerValue = {\n hours: value?.getHours() ?? 0,\n minutes: value?.getMinutes() ?? 0,\n seconds: enableSeconds ? (value?.getSeconds() ?? 0) : undefined,\n };\n\n const panel = (\n <div className={panelClass}>\n <TimeWheels\n value={spinnerValue}\n onChange={handleSpinnerChange}\n hourFormat={effectiveHourFormat}\n enableSeconds={enableSeconds}\n incrementHours={incrementHours}\n incrementMinutes={incrementMinutes}\n incrementSeconds={incrementSeconds}\n unselectableTimes={unselectableTimes}\n color={color}\n size={size}\n disabled={disabled}\n // The popover panel takes `popoverId`, so the wheels inside it take\n // one of their own. Inline there is no panel, and the wheels keep\n // the id they released with.\n id={inline ? popoverId : `${popoverId}-time`}\n labels={labels}\n itemHeight={wheelItemHeight}\n audioTick={effectiveAudioTick}\n onCommit={() => setOpen(false)}\n />\n {/* Footer is popover-only. Desktop gets the OK / Now / Cancel triad;\n mobile drops to an iOS-style \"Reset / ✓\" pair to match the OS\n picker's footer affordances and free up vertical space on small\n screens. */}\n {!inline && !isSmallViewport && (\n <Buttons className={footerClass} hasAddons>\n <button\n type=\"button\"\n className={footerOkClass}\n onClick={() => setOpen(false)}\n >\n {t.ok}\n </button>\n <button\n type=\"button\"\n className={footerButton}\n onClick={() => {\n commitValue(\n snapTimeToIncrement(new Date(), {\n incrementHours,\n incrementMinutes,\n incrementSeconds,\n enableSeconds,\n })\n );\n setOpen(false);\n }}\n >\n {t.now}\n </button>\n <button\n type=\"button\"\n className={footerButton}\n onClick={() => {\n commitValue(valueAtOpenRef.current);\n setOpen(false);\n }}\n >\n {t.cancel}\n </button>\n </Buttons>\n )}\n {!inline && isSmallViewport && (\n <div className={mobileFooterClass}>\n <button\n type=\"button\"\n className={mobileFooterResetClass}\n onClick={() => {\n commitValue(valueAtOpenRef.current);\n setOpen(false);\n }}\n >\n {t.reset}\n </button>\n <button\n type=\"button\"\n className={mobileFooterDoneClass}\n aria-label={t.done}\n onClick={() => setOpen(false)}\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 22 22\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5 11l4 4 8-8\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n )}\n </div>\n );\n\n if (inline) {\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n className={classNames(containerClass, bulmaHelperClasses, className)}\n >\n {panel}\n {name && (\n <input\n type=\"hidden\"\n name={name}\n form={form}\n value={value ? toIsoTime(value, enableSeconds) : ''}\n required={required}\n />\n )}\n </div>\n );\n }\n\n return (\n <div\n ref={containerRef}\n className={classNames(containerClass, bulmaHelperClasses, className)}\n {...cleanRest}\n >\n <input\n ref={combinedRef}\n type=\"text\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={popoverId}\n autoComplete=\"off\"\n className={inputClass}\n value={text}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={inputReadOnlyAttr}\n name={name}\n form={form}\n required={required}\n id={id}\n {...inputHandlers}\n />\n {popover && triggerIcon && (\n <button\n type=\"button\"\n className={triggerClass}\n onClick={() => {\n if (canOpen) setOpen(!open);\n }}\n disabled={!canOpen}\n aria-label={t.chooseTime}\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={() => setOpen(false)}\n anchorRef={containerRef}\n position={position}\n appendToBody={appendToBody}\n ariaLabel={t.chooseTime}\n id={popoverId}\n restoreFocusRef={inputRef}\n >\n {panel}\n </PickerPopover>\n )}\n </div>\n );\n }\n);\n\nTimeInputBase.displayName = 'TimeInputBase';\n\nexport default TimeInputBase;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -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 { useId } from 'react';
|
|
3
|
-
import { useFieldLabelElementId, useFieldLabelId, useFieldLabelFor } from './FormContext.js';
|
|
3
|
+
import { useFieldLabelElementId, useFieldLabelId, useFieldLabelFor, useReportFieldLabelFor } from './FormContext.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Associates the convenience `label` prop with its control (#368): generates
|
|
@@ -10,8 +10,10 @@ import { useFieldLabelElementId, useFieldLabelId, useFieldLabelFor } from './For
|
|
|
10
10
|
* generation entirely: the user has taken over the association (#495 presence
|
|
11
11
|
* semantics). When the control renders no label of its own, it adopts the id
|
|
12
12
|
* a labeled Field around it offers, the way the bases do, so that Field's
|
|
13
|
-
* label names it (#939); a user `id` still wins there.
|
|
14
|
-
*
|
|
13
|
+
* label names it (#939); a user `id` still wins there. It tells that Field
|
|
14
|
+
* when the control took its id, since the Field's label drops a `for`
|
|
15
|
+
* nothing took (#1004). With `needsLabelId` it also returns the id of
|
|
16
|
+
* whichever label names the control (#981).
|
|
15
17
|
* Internal; not part of the public API.
|
|
16
18
|
*/
|
|
17
19
|
function useAutoLabelId({ label, id, labelProps, rendersLabel, hasInput = true, needsLabelId = false, }) {
|
|
@@ -32,6 +34,9 @@ function useAutoLabelId({ label, id, labelProps, rendersLabel, hasInput = true,
|
|
|
32
34
|
const userWired = !!labelProps && 'htmlFor' in labelProps;
|
|
33
35
|
const adopted = !active && hasInput ? fieldLabelId : undefined;
|
|
34
36
|
const controlId = id ?? (active && !userWired ? generatedId : adopted);
|
|
37
|
+
// Tells a labeled Field around the control when its label's `for` names
|
|
38
|
+
// the control, since it drops a `for` nothing took (#1004).
|
|
39
|
+
useReportFieldLabelFor(fieldLabelId !== undefined && controlId === fieldLabelId);
|
|
35
40
|
const ownLabelProps = { htmlFor: controlId, ...labelProps };
|
|
36
41
|
const labelTarget = active ? ownLabelProps.htmlFor : fieldLabelFor.htmlFor;
|
|
37
42
|
const labelled = !!controlId && labelTarget === controlId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAutoLabelId.js","sources":["../../../src/form/useAutoLabelId.ts"],"sourcesContent":["import React, { useId } from 'react';\nimport type { FieldProps } from './Field';\nimport {\n useFieldLabelElementId,\n useFieldLabelFor,\n useFieldLabelId,\n} from './FormContext';\n\ninterface UseAutoLabelIdOptions {\n /** The convenience `label` prop as passed by the caller. */\n label: React.ReactNode;\n /** User-supplied id for the control, if any. */\n id?: string;\n /** User-supplied labelProps, if any. */\n labelProps?: FieldProps['labelProps'];\n /**\n * True when this render actually outputs the label wired to a control —\n * false inside an outer Field (label is dropped), in variants that render\n * no Field, and in modes with no labellable control (e.g. inline pickers).\n */\n rendersLabel: boolean;\n /**\n * False when this render has no input to label at all (an inline picker),\n * so it takes no id from a surrounding Field either. Defaults to true.\n */\n hasInput?: boolean;\n /**\n * True when the control also points `aria-labelledby` at the label, as a\n * range Slider's thumbs (#981) and Autocomplete's suggestion list (#998)\n * do, so it needs the label's own id. Its own label then gets one\n * (`labelProps.id` when given, otherwise a generated one), and the hook\n * returns it, or a surrounding Field's, as `labelId`.\n */\n needsLabelId?: boolean;\n}\n\n/**\n * Associates the convenience `label` prop with its control (#368): generates\n * an id for the control and returns labelProps carrying a matching `htmlFor`.\n * A user-supplied `id` is used as the target instead of the generated one, and\n * an explicit `htmlFor` key in labelProps — even set to `undefined` — disables\n * generation entirely: the user has taken over the association (#495 presence\n * semantics). When the control renders no label of its own, it adopts the id\n * a labeled Field around it offers, the way the bases do, so that Field's\n * label names it (#939); a user `id` still wins there. With `needsLabelId`\n * it also returns the id of whichever label names the control (#981).\n * Internal; not part of the public API.\n */\nexport function useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel,\n hasInput = true,\n needsLabelId = false,\n}: UseAutoLabelIdOptions): {\n controlId: string | undefined;\n fieldLabelProps: FieldProps['labelProps'] | undefined;\n /** Whether a rendered label, its own or a surrounding Field's, points at `controlId`. */\n labelled: boolean;\n /**\n * With `needsLabelId`, the id of the label that names `controlId`, its own\n * or a surrounding Field's. Undefined when no label names it, or when a\n * Field's label wired by hand names it without an `id` in its labelProps,\n * since the Field generates none for a label wired by hand.\n */\n labelId: string | undefined;\n} {\n // Called unconditionally per the rules of hooks; SSR-safe on React 18 and 19.\n const generatedId = useId();\n // Read outside the control's own Field, so it is set only when an outer\n // Field holds the control, which then renders no label of its own.\n const fieldLabelId = useFieldLabelId();\n // What an outer Field's label points at, even when wired by hand, and the\n // id that label renders with, read together so the id is that label's.\n // Set in `grouped`/`hasAddons` Fields too when the label is wired by hand,\n // since its `for` names this one control whatever the layout (see Field).\n const fieldLabelFor = useFieldLabelFor();\n // Truthiness mirrors Field's own `if (label)` render gate.\n const active = !!label && rendersLabel;\n // Presence, not truthiness: `htmlFor: undefined` is an explicit opt-out and\n // must not leave an orphan generated id on the control.\n const userWired = !!labelProps && 'htmlFor' in labelProps;\n const adopted = !active && hasInput ? fieldLabelId : undefined;\n const controlId = id ?? (active && !userWired ? generatedId : adopted);\n const ownLabelProps = { htmlFor: controlId, ...labelProps };\n const labelTarget = active ? ownLabelProps.htmlFor : fieldLabelFor.htmlFor;\n const labelled = !!controlId && labelTarget === controlId;\n // Only a label that names the control gets an id to point at, with the\n // suffix Field gives its own, from an id that is already unique.\n const ownLabelId =\n needsLabelId && active && labelled\n ? (labelProps?.id ?? `${generatedId}-label`)\n : undefined;\n // Inactive with a label still means an own Field may render it (pickers'\n // inline mode, Taginput at maxTags) — the explicit `htmlFor: undefined`\n // tells Field the association is owned here, so it must not generate one\n // that would dangle (#495 presence semantics).\n const fieldLabelProps = active\n ? ownLabelId\n ? { ...ownLabelProps, id: ownLabelId }\n : ownLabelProps\n : label\n ? { htmlFor: undefined, ...labelProps }\n : labelProps;\n const labelId =\n needsLabelId && labelled\n ? active\n ? ownLabelId\n : fieldLabelFor.id\n : undefined;\n return { controlId, fieldLabelProps, labelled, labelId };\n}\n\ninterface UseAutoLabelledByOptions {\n /** The convenience `label` prop as passed by the caller. */\n label: React.ReactNode;\n /** User-supplied labelProps, if any. */\n labelProps?: FieldProps['labelProps'];\n /** True when this render actually outputs the label naming the group. */\n rendersLabel: boolean;\n /**\n * The caller's remaining props. A non-empty `aria-label` among them names\n * the group, and so does any `aria-labelledby` key, even an undefined one,\n * since the group spreads them after its own attribute. Either keeps every\n * label off the group, its own and a surrounding Field's alike.\n */\n callerProps: object;\n}\n\n/**\n * Group-input counterpart of {@link useAutoLabelId} (#494): a group of\n * controls cannot take a single `htmlFor`, so instead the rendered `<label>`\n * gets a generated id and the group container points at it with\n * `aria-labelledby`. A user-supplied `labelProps.id` is used as the target\n * instead of generating one. Any caller `htmlFor` is stripped — a group label\n * names the group, never a single control — so the merged labelProps always\n * carry an explicit `htmlFor: undefined`. When the group renders no label of\n * its own, it points at the label of a labeled Field around it instead\n * (#939). A caller who named the group with `aria-label` or\n * `aria-labelledby` gets no `aria-labelledby` from either label, so their\n * name wins wherever the label sits.\n * Internal; not part of the public API.\n */\nexport function useAutoLabelledBy({\n label,\n labelProps,\n rendersLabel,\n callerProps,\n}: UseAutoLabelledByOptions): {\n ariaLabelledBy: string | undefined;\n fieldLabelProps: FieldProps['labelProps'] | undefined;\n} {\n // Called unconditionally per the rules of hooks; SSR-safe on React 18 and 19.\n const generatedId = useId();\n // Set only when an outer Field holds the group (see useAutoLabelId).\n const fieldLabelElementId = useFieldLabelElementId();\n const active = !!label && rendersLabel;\n const labelId = labelProps?.id ?? (active ? generatedId : undefined);\n const fieldLabelProps = active\n ? { ...labelProps, id: labelId, htmlFor: undefined }\n : labelProps;\n const aria = callerProps as React.AriaAttributes;\n // Presence for aria-labelledby: the caller's key replaces the attribute\n // through the spread whatever its value, and pointing it at a label would\n // only take a Rate's fallback name away. Checked before either label, so\n // the caller's name wins over the group's own `label` as it does over a\n // Field's, the way an aria-label beats a `<label for>` on a single input.\n const callerNamed = !!aria['aria-label'] || 'aria-labelledby' in aria;\n const ariaLabelledBy = callerNamed\n ? undefined\n : active\n ? labelId\n : fieldLabelElementId;\n return { ariaLabelledBy, fieldLabelProps };\n}\n"],"names":[],"mappings":";;;;AAoCA;;;;;;;;;;;AAWG;SACa,cAAc,CAAC,EAC7B,KAAK,EACL,EAAE,EACF,UAAU,EACV,YAAY,EACZ,QAAQ,GAAG,IAAI,EACf,YAAY,GAAG,KAAK,GACE,EAAA;;AActB,IAAA,MAAM,WAAW,GAAG,KAAK,EAAE;;;AAG3B,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;;;;;AAKtC,IAAA,MAAM,aAAa,GAAG,gBAAgB,EAAE;;AAExC,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,YAAY;;;IAGtC,MAAM,SAAS,GAAG,CAAC,CAAC,UAAU,IAAI,SAAS,IAAI,UAAU;AACzD,IAAA,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,QAAQ,GAAG,YAAY,GAAG,SAAS;AAC9D,IAAA,MAAM,SAAS,GAAG,EAAE,KAAK,MAAM,IAAI,CAAC,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACtE,MAAM,aAAa,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE;AAC3D,IAAA,MAAM,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,OAAO,GAAG,aAAa,CAAC,OAAO;IAC1E,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,IAAI,WAAW,KAAK,SAAS;;;AAGzD,IAAA,MAAM,UAAU,GACd,YAAY,IAAI,MAAM,IAAI;WACrB,UAAU,EAAE,EAAE,IAAI,CAAA,EAAG,WAAW,CAAA,MAAA,CAAQ;UACzC,SAAS;;;;;IAKf,MAAM,eAAe,GAAG;AACtB,UAAE;cACE,EAAE,GAAG,aAAa,EAAE,EAAE,EAAE,UAAU;AACpC,cAAE;AACJ,UAAE;cACE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU;cACnC,UAAU;AAChB,IAAA,MAAM,OAAO,GACX,YAAY,IAAI;AACd,UAAE;AACA,cAAE;cACA,aAAa,CAAC;UAChB,SAAS;IACf,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAE;AAC1D;AAkBA;;;;;;;;;;;;;AAaG;AACG,SAAU,iBAAiB,CAAC,EAChC,KAAK,EACL,UAAU,EACV,YAAY,EACZ,WAAW,GACc,EAAA;;AAKzB,IAAA,MAAM,WAAW,GAAG,KAAK,EAAE;;AAE3B,IAAA,MAAM,mBAAmB,GAAG,sBAAsB,EAAE;AACpD,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,YAAY;AACtC,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,EAAE,KAAK,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACpE,MAAM,eAAe,GAAG;AACtB,UAAE,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS;UAChD,UAAU;IACd,MAAM,IAAI,GAAG,WAAmC;;;;;;AAMhD,IAAA,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,iBAAiB,IAAI,IAAI;IACrE,MAAM,cAAc,GAAG;AACrB,UAAE;AACF,UAAE;AACA,cAAE;cACA,mBAAmB;AACzB,IAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE;AAC5C;;"}
|
|
1
|
+
{"version":3,"file":"useAutoLabelId.js","sources":["../../../src/form/useAutoLabelId.ts"],"sourcesContent":["import React, { useId } from 'react';\nimport type { FieldProps } from './Field';\nimport {\n useFieldLabelElementId,\n useFieldLabelFor,\n useFieldLabelId,\n useReportFieldLabelFor,\n} from './FormContext';\n\ninterface UseAutoLabelIdOptions {\n /** The convenience `label` prop as passed by the caller. */\n label: React.ReactNode;\n /** User-supplied id for the control, if any. */\n id?: string;\n /** User-supplied labelProps, if any. */\n labelProps?: FieldProps['labelProps'];\n /**\n * True when this render actually outputs the label wired to a control —\n * false inside an outer Field (label is dropped), in variants that render\n * no Field, and in modes with no labellable control (e.g. inline pickers).\n */\n rendersLabel: boolean;\n /**\n * False when this render has no input to label at all (an inline picker),\n * so it takes no id from a surrounding Field either. Defaults to true.\n */\n hasInput?: boolean;\n /**\n * True when the control also points `aria-labelledby` at the label, as a\n * range Slider's thumbs (#981) and Autocomplete's suggestion list (#998)\n * do, so it needs the label's own id. Its own label then gets one\n * (`labelProps.id` when given, otherwise a generated one), and the hook\n * returns it, or a surrounding Field's, as `labelId`.\n */\n needsLabelId?: boolean;\n}\n\n/**\n * Associates the convenience `label` prop with its control (#368): generates\n * an id for the control and returns labelProps carrying a matching `htmlFor`.\n * A user-supplied `id` is used as the target instead of the generated one, and\n * an explicit `htmlFor` key in labelProps — even set to `undefined` — disables\n * generation entirely: the user has taken over the association (#495 presence\n * semantics). When the control renders no label of its own, it adopts the id\n * a labeled Field around it offers, the way the bases do, so that Field's\n * label names it (#939); a user `id` still wins there. It tells that Field\n * when the control took its id, since the Field's label drops a `for`\n * nothing took (#1004). With `needsLabelId` it also returns the id of\n * whichever label names the control (#981).\n * Internal; not part of the public API.\n */\nexport function useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel,\n hasInput = true,\n needsLabelId = false,\n}: UseAutoLabelIdOptions): {\n controlId: string | undefined;\n fieldLabelProps: FieldProps['labelProps'] | undefined;\n /** Whether a rendered label, its own or a surrounding Field's, points at `controlId`. */\n labelled: boolean;\n /**\n * With `needsLabelId`, the id of the label that names `controlId`, its own\n * or a surrounding Field's. Undefined when no label names it, or when a\n * Field's label wired by hand names it without an `id` in its labelProps,\n * since the Field generates none for a label wired by hand.\n */\n labelId: string | undefined;\n} {\n // Called unconditionally per the rules of hooks; SSR-safe on React 18 and 19.\n const generatedId = useId();\n // Read outside the control's own Field, so it is set only when an outer\n // Field holds the control, which then renders no label of its own.\n const fieldLabelId = useFieldLabelId();\n // What an outer Field's label points at, even when wired by hand, and the\n // id that label renders with, read together so the id is that label's.\n // Set in `grouped`/`hasAddons` Fields too when the label is wired by hand,\n // since its `for` names this one control whatever the layout (see Field).\n const fieldLabelFor = useFieldLabelFor();\n // Truthiness mirrors Field's own `if (label)` render gate.\n const active = !!label && rendersLabel;\n // Presence, not truthiness: `htmlFor: undefined` is an explicit opt-out and\n // must not leave an orphan generated id on the control.\n const userWired = !!labelProps && 'htmlFor' in labelProps;\n const adopted = !active && hasInput ? fieldLabelId : undefined;\n const controlId = id ?? (active && !userWired ? generatedId : adopted);\n // Tells a labeled Field around the control when its label's `for` names\n // the control, since it drops a `for` nothing took (#1004).\n useReportFieldLabelFor(\n fieldLabelId !== undefined && controlId === fieldLabelId\n );\n const ownLabelProps = { htmlFor: controlId, ...labelProps };\n const labelTarget = active ? ownLabelProps.htmlFor : fieldLabelFor.htmlFor;\n const labelled = !!controlId && labelTarget === controlId;\n // Only a label that names the control gets an id to point at, with the\n // suffix Field gives its own, from an id that is already unique.\n const ownLabelId =\n needsLabelId && active && labelled\n ? (labelProps?.id ?? `${generatedId}-label`)\n : undefined;\n // Inactive with a label still means an own Field may render it (pickers'\n // inline mode, Taginput at maxTags) — the explicit `htmlFor: undefined`\n // tells Field the association is owned here, so it must not generate one\n // that would dangle (#495 presence semantics).\n const fieldLabelProps = active\n ? ownLabelId\n ? { ...ownLabelProps, id: ownLabelId }\n : ownLabelProps\n : label\n ? { htmlFor: undefined, ...labelProps }\n : labelProps;\n const labelId =\n needsLabelId && labelled\n ? active\n ? ownLabelId\n : fieldLabelFor.id\n : undefined;\n return { controlId, fieldLabelProps, labelled, labelId };\n}\n\ninterface UseAutoLabelledByOptions {\n /** The convenience `label` prop as passed by the caller. */\n label: React.ReactNode;\n /** User-supplied labelProps, if any. */\n labelProps?: FieldProps['labelProps'];\n /** True when this render actually outputs the label naming the group. */\n rendersLabel: boolean;\n /**\n * The caller's remaining props. A non-empty `aria-label` among them names\n * the group, and so does any `aria-labelledby` key, even an undefined one,\n * since the group spreads them after its own attribute. Either keeps every\n * label off the group, its own and a surrounding Field's alike.\n */\n callerProps: object;\n}\n\n/**\n * Group-input counterpart of {@link useAutoLabelId} (#494): a group of\n * controls cannot take a single `htmlFor`, so instead the rendered `<label>`\n * gets a generated id and the group container points at it with\n * `aria-labelledby`. A user-supplied `labelProps.id` is used as the target\n * instead of generating one. Any caller `htmlFor` is stripped — a group label\n * names the group, never a single control — so the merged labelProps always\n * carry an explicit `htmlFor: undefined`. When the group renders no label of\n * its own, it points at the label of a labeled Field around it instead\n * (#939). A caller who named the group with `aria-label` or\n * `aria-labelledby` gets no `aria-labelledby` from either label, so their\n * name wins wherever the label sits.\n * Internal; not part of the public API.\n */\nexport function useAutoLabelledBy({\n label,\n labelProps,\n rendersLabel,\n callerProps,\n}: UseAutoLabelledByOptions): {\n ariaLabelledBy: string | undefined;\n fieldLabelProps: FieldProps['labelProps'] | undefined;\n} {\n // Called unconditionally per the rules of hooks; SSR-safe on React 18 and 19.\n const generatedId = useId();\n // Set only when an outer Field holds the group (see useAutoLabelId).\n const fieldLabelElementId = useFieldLabelElementId();\n const active = !!label && rendersLabel;\n const labelId = labelProps?.id ?? (active ? generatedId : undefined);\n const fieldLabelProps = active\n ? { ...labelProps, id: labelId, htmlFor: undefined }\n : labelProps;\n const aria = callerProps as React.AriaAttributes;\n // Presence for aria-labelledby: the caller's key replaces the attribute\n // through the spread whatever its value, and pointing it at a label would\n // only take a Rate's fallback name away. Checked before either label, so\n // the caller's name wins over the group's own `label` as it does over a\n // Field's, the way an aria-label beats a `<label for>` on a single input.\n const callerNamed = !!aria['aria-label'] || 'aria-labelledby' in aria;\n const ariaLabelledBy = callerNamed\n ? undefined\n : active\n ? labelId\n : fieldLabelElementId;\n return { ariaLabelledBy, fieldLabelProps };\n}\n"],"names":[],"mappings":";;;;AAqCA;;;;;;;;;;;;;AAaG;SACa,cAAc,CAAC,EAC7B,KAAK,EACL,EAAE,EACF,UAAU,EACV,YAAY,EACZ,QAAQ,GAAG,IAAI,EACf,YAAY,GAAG,KAAK,GACE,EAAA;;AActB,IAAA,MAAM,WAAW,GAAG,KAAK,EAAE;;;AAG3B,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;;;;;AAKtC,IAAA,MAAM,aAAa,GAAG,gBAAgB,EAAE;;AAExC,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,YAAY;;;IAGtC,MAAM,SAAS,GAAG,CAAC,CAAC,UAAU,IAAI,SAAS,IAAI,UAAU;AACzD,IAAA,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,QAAQ,GAAG,YAAY,GAAG,SAAS;AAC9D,IAAA,MAAM,SAAS,GAAG,EAAE,KAAK,MAAM,IAAI,CAAC,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;;;IAGtE,sBAAsB,CACpB,YAAY,KAAK,SAAS,IAAI,SAAS,KAAK,YAAY,CACzD;IACD,MAAM,aAAa,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE;AAC3D,IAAA,MAAM,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,OAAO,GAAG,aAAa,CAAC,OAAO;IAC1E,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,IAAI,WAAW,KAAK,SAAS;;;AAGzD,IAAA,MAAM,UAAU,GACd,YAAY,IAAI,MAAM,IAAI;WACrB,UAAU,EAAE,EAAE,IAAI,CAAA,EAAG,WAAW,CAAA,MAAA,CAAQ;UACzC,SAAS;;;;;IAKf,MAAM,eAAe,GAAG;AACtB,UAAE;cACE,EAAE,GAAG,aAAa,EAAE,EAAE,EAAE,UAAU;AACpC,cAAE;AACJ,UAAE;cACE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU;cACnC,UAAU;AAChB,IAAA,MAAM,OAAO,GACX,YAAY,IAAI;AACd,UAAE;AACA,cAAE;cACA,aAAa,CAAC;UAChB,SAAS;IACf,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAE;AAC1D;AAkBA;;;;;;;;;;;;;AAaG;AACG,SAAU,iBAAiB,CAAC,EAChC,KAAK,EACL,UAAU,EACV,YAAY,EACZ,WAAW,GACc,EAAA;;AAKzB,IAAA,MAAM,WAAW,GAAG,KAAK,EAAE;;AAE3B,IAAA,MAAM,mBAAmB,GAAG,sBAAsB,EAAE;AACpD,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,YAAY;AACtC,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,EAAE,KAAK,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACpE,MAAM,eAAe,GAAG;AACtB,UAAE,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS;UAChD,UAAU;IACd,MAAM,IAAI,GAAG,WAAmC;;;;;;AAMhD,IAAA,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,iBAAiB,IAAI,IAAI;IACrE,MAAM,cAAc,GAAG;AACrB,UAAE;AACF,UAAE;AACA,cAAE;cACA,mBAAmB;AACzB,IAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE;AAC5C;;"}
|