@allxsmith/bestax-bulma 5.34.0 → 5.34.2
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/esm/components/Dropdown.js +8 -3
- package/dist/esm/components/Dropdown.js.map +1 -1
- package/dist/esm/components/Loading.js +5 -4
- package/dist/esm/components/Loading.js.map +1 -1
- package/dist/esm/components/Modal.js +11 -4
- package/dist/esm/components/Modal.js.map +1 -1
- package/dist/esm/components/Sidebar.js +5 -4
- package/dist/esm/components/Sidebar.js.map +1 -1
- package/dist/esm/components/Toast.js +7 -5
- package/dist/esm/components/Toast.js.map +1 -1
- package/dist/esm/form/Autocomplete.js +17 -2
- package/dist/esm/form/Autocomplete.js.map +1 -1
- package/dist/esm/form/Field.js +3 -3
- package/dist/esm/form/Field.js.map +1 -1
- package/dist/esm/form/FormContext.js +2 -1
- package/dist/esm/form/FormContext.js.map +1 -1
- package/dist/esm/form/Taginput.js +40 -6
- package/dist/esm/form/Taginput.js.map +1 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js +11 -3
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
- package/dist/esm/form/useAutoLabelId.js.map +1 -1
- package/dist/index.cjs +107 -34
- package/dist/index.cjs.map +1 -1
- package/dist/types/components/Loading.d.ts +5 -1
- package/dist/types/components/Modal.d.ts +4 -1
- package/dist/types/components/Sidebar.d.ts +5 -1
- package/dist/types/components/Toast.d.ts +4 -1
- package/dist/types/form/Autocomplete.d.ts +13 -2
- package/dist/types/form/Field.d.ts +5 -5
- package/dist/types/form/FormContext.d.ts +2 -1
- package/dist/types/form/Taginput.d.ts +8 -3
- package/dist/types/form/useAutoLabelId.d.ts +2 -2
- package/dist/types-cjs/components/Loading.d.ts +5 -1
- package/dist/types-cjs/components/Modal.d.ts +4 -1
- package/dist/types-cjs/components/Sidebar.d.ts +5 -1
- package/dist/types-cjs/components/Toast.d.ts +4 -1
- package/dist/types-cjs/form/Autocomplete.d.ts +13 -2
- package/dist/types-cjs/form/Field.d.ts +5 -5
- package/dist/types-cjs/form/FormContext.d.ts +2 -1
- package/dist/types-cjs/form/Taginput.d.ts +8 -3
- package/dist/types-cjs/form/useAutoLabelId.d.ts +2 -2
- package/package.json +1 -1
|
@@ -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 { 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":"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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 and Taginput's suggestion lists\n * (#998, #1082) 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;;;;;;;;;;;;;;;;;AAiBG;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;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { forwardRef, useRef, useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import { forwardRef, useRef, useState, useId, useEffect, useCallback } from 'react';
|
|
4
4
|
import { classNames, usePrefixedClassNames, prefixedClassNames } from '../helpers/classNames.js';
|
|
5
5
|
import { useConfig, useIconLibrary } from '../helpers/Config.js';
|
|
6
6
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
@@ -35,7 +35,7 @@ import { Icon } from '../elements/Icon.js';
|
|
|
35
35
|
*/
|
|
36
36
|
const Taginput = forwardRef(({
|
|
37
37
|
// Field props
|
|
38
|
-
label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, value: controlledValue, defaultValue = [], data
|
|
38
|
+
label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, value: controlledValue, defaultValue = [], data: dataProp, placeholder, field = 'label', allowNew = true, allowDuplicates = false, openOnFocus = false, removeOnKeys = true, confirmKeys = ['Enter', ','], closable = true, attached = false, maxTags, maxlength, disabled = false, readonly = false, rounded = false, ellipsis = false, hasCounter = true, onPasteSeparators = [','], beforeAdding, createTag, keepFirst = false, keepOpen = true, loading = false, ariaCloseLabel, icon, iconLibrary: iconLibraryProp, iconVariant, iconFeatures, color, tagColor, size, onChange, onAdd, onRemove, onTyping, tagTemplate, name, form, id, className, ...props }, ref) => {
|
|
39
39
|
const insideField = useInsideField();
|
|
40
40
|
const insideControl = useInsideControl();
|
|
41
41
|
const ownField = rendersOwnField('Taginput', {
|
|
@@ -58,17 +58,26 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
58
58
|
const [inputValue, setInputValue] = useState('');
|
|
59
59
|
const [isActive, setIsActive] = useState(false);
|
|
60
60
|
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
|
61
|
+
const listboxId = `${useId()}-listbox`;
|
|
62
|
+
// With `data` the input offers suggestions, so it's a combobox, even
|
|
63
|
+
// while none match. Without it there's never a list, so it stays a plain
|
|
64
|
+
// text field.
|
|
65
|
+
const hasSuggestions = dataProp !== undefined;
|
|
66
|
+
const data = dataProp ?? [];
|
|
61
67
|
// Use controlled or internal tags
|
|
62
68
|
const tags = controlledValue !== undefined ? controlledValue : internalTags;
|
|
63
69
|
const isMaxReached = maxTags !== undefined && tags.length >= maxTags;
|
|
64
70
|
// At the tag limit the text input is not rendered, so there is nothing to
|
|
65
|
-
// wire a label to, its own or a surrounding Field's.
|
|
66
|
-
|
|
71
|
+
// wire a label to, its own or a surrounding Field's. The suggestion list
|
|
72
|
+
// points `aria-labelledby` at the label that names the input, so with
|
|
73
|
+
// suggestions it needs that label's id.
|
|
74
|
+
const { controlId, fieldLabelProps, labelled, labelId: listLabelId, } = useAutoLabelId({
|
|
67
75
|
label,
|
|
68
76
|
id,
|
|
69
77
|
labelProps,
|
|
70
78
|
rendersLabel: ownField && !isMaxReached,
|
|
71
79
|
hasInput: !isMaxReached,
|
|
80
|
+
needsLabelId: hasSuggestions,
|
|
72
81
|
});
|
|
73
82
|
// Get display value from tag
|
|
74
83
|
const getDisplayValue = (tag) => {
|
|
@@ -88,6 +97,7 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
88
97
|
const hasInput = inputValue || (openOnFocus && isActive);
|
|
89
98
|
return matchesInput && notAlreadyAdded && hasInput;
|
|
90
99
|
});
|
|
100
|
+
const listOpen = isActive && filteredData.length > 0;
|
|
91
101
|
// keepFirst: auto-highlight first item when dropdown opens
|
|
92
102
|
useEffect(() => {
|
|
93
103
|
if (keepFirst && isActive && filteredData.length > 0) {
|
|
@@ -256,6 +266,10 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
256
266
|
}
|
|
257
267
|
break;
|
|
258
268
|
case 'Escape':
|
|
269
|
+
// Closing the suggestions claims the key, so a Modal around the
|
|
270
|
+
// field stays open. With none showing, the key goes on to it.
|
|
271
|
+
if (isActive && filteredData.length > 0)
|
|
272
|
+
e.preventDefault();
|
|
259
273
|
setIsActive(false);
|
|
260
274
|
setHighlightedIndex(-1);
|
|
261
275
|
break;
|
|
@@ -328,15 +342,35 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
328
342
|
[`is-${messageColor}`]: !!messageColor,
|
|
329
343
|
});
|
|
330
344
|
const messageEl = message ? jsx("p", { className: helpClass, children: message }) : null;
|
|
345
|
+
// The combobox controls its listbox and points at the highlighted option,
|
|
346
|
+
// the way Autocomplete's does. The listbox takes its name from the label
|
|
347
|
+
// that names the combobox, the one this renders or a surrounding Field's,
|
|
348
|
+
// and keeps a fallback name when no label names it or the one that does
|
|
349
|
+
// has no id to point at. While no suggestion matches there's no listbox,
|
|
350
|
+
// so the combobox is collapsed and points at nothing. It skips a
|
|
351
|
+
// highlighted suggestion that's blank once trimmed, since that one can't
|
|
352
|
+
// become a tag, and the option it points at is the one marked selected.
|
|
353
|
+
const optionId = (index) => `${listboxId}-${index}`;
|
|
354
|
+
const activeOptionId = listOpen && filteredData[highlightedIndex]?.trim()
|
|
355
|
+
? optionId(highlightedIndex)
|
|
356
|
+
: undefined;
|
|
357
|
+
const comboboxProps = {
|
|
358
|
+
role: 'combobox',
|
|
359
|
+
'aria-expanded': listOpen,
|
|
360
|
+
'aria-controls': listOpen ? listboxId : undefined,
|
|
361
|
+
'aria-activedescendant': activeOptionId,
|
|
362
|
+
'aria-haspopup': 'listbox',
|
|
363
|
+
'aria-autocomplete': 'list',
|
|
364
|
+
};
|
|
331
365
|
const taginputElement = (jsxs("div", { ref: containerRef, className: combinedClasses, onClick: handleContainerClick, ...rest, children: [jsxs("div", { className: containerClasses, children: [icon && (jsx(Icon, { name: icon, library: resolvedLibrary, variant: iconVariant, features: iconFeatures, containerClassName: pcn('icon', 'is-left') })), jsxs("div", { className: tagsClasses, children: [tags.map((tag, index) => {
|
|
332
366
|
const displayVal = getDisplayValue(tag);
|
|
333
367
|
return (jsxs("span", { className: tagClasses, children: [tagTemplate ? (tagTemplate(tag)) : ellipsis ? (jsx("span", { title: displayVal, children: displayVal })) : (displayVal), closable && !disabled && !readonly && (jsx("button", { type: "button", className: pcn('delete', 'is-small'), onClick: e => {
|
|
334
368
|
e.stopPropagation();
|
|
335
369
|
removeTag(index);
|
|
336
370
|
}, "aria-label": ariaCloseLabel || `Remove ${displayVal}` }))] }, index));
|
|
337
|
-
}), !isMaxReached && (jsx("input", { ref: combinedRef, type: "text", className: inputClasses, id: controlId, value: inputValue, placeholder: tags.length === 0 ? placeholder : undefined, disabled: disabled, readOnly: readonly, maxLength: maxlength, onChange: handleInputChange, onFocus: handleFocus, onKeyDown: handleKeyDown, onPaste: handlePaste, "aria-label": labelled ? undefined : 'Add tag' }))] }), loading && (jsx("span", { className: iconRightClass, children: jsx("span", { className: loaderClass }) }))] }),
|
|
371
|
+
}), !isMaxReached && (jsx("input", { ref: combinedRef, type: "text", className: inputClasses, id: controlId, value: inputValue, placeholder: tags.length === 0 ? placeholder : undefined, disabled: disabled, readOnly: readonly, maxLength: maxlength, onChange: handleInputChange, onFocus: handleFocus, onKeyDown: handleKeyDown, onPaste: handlePaste, ...(hasSuggestions && comboboxProps), "aria-label": labelled ? undefined : 'Add tag' }))] }), loading && (jsx("span", { className: iconRightClass, children: jsx("span", { className: loaderClass }) }))] }), listOpen && (jsx("div", { className: dropdownMenuClasses, children: jsx("div", { ref: dropdownRef, id: listboxId, className: dropdownContentClasses, role: "listbox", "aria-labelledby": listLabelId, "aria-label": listLabelId ? undefined : 'Suggestions', children: filteredData.map((item, index) => (jsx("a", { id: optionId(index), className: pcn('dropdown-item', {
|
|
338
372
|
'is-active': index === highlightedIndex,
|
|
339
|
-
}), onClick: () => addTag(item), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index ===
|
|
373
|
+
}), onClick: () => addTag(item), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": optionId(index) === activeOptionId, children: item }, index))) }) })), showCounter && jsx("small", { className: counterClasses, children: counterText }), name &&
|
|
340
374
|
tags.map((tag, i) => (jsx("input", { type: "hidden", name: name, value: getDisplayValue(tag), form: form }, `tag-input-${i}`)))] }));
|
|
341
375
|
if (ownField) {
|
|
342
376
|
return (jsxs(Field, { label: label, labelSize: labelSize, labelProps: fieldLabelProps, horizontal: horizontal, className: fieldClassName, children: [taginputElement, messageEl] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Taginput.js","sources":["../../../src/form/Taginput.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useState,\n useRef,\n useEffect,\n useCallback,\n} from 'react';\nimport {\n classNames,\n usePrefixedClassNames,\n prefixedClassNames,\n} from '../helpers/classNames';\nimport { useConfig, useIconLibrary } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { isEventInside } from '../helpers/shadowDom';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n} from './FormContext';\nimport { Field } from './Field';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelId } from './useAutoLabelId';\nimport { Icon } from '../elements/Icon';\n\n/**\n * Represents a tag item object with a value and optional label.\n */\nexport interface TaginputItem {\n /** The tag value. */\n value: string;\n /** Display label (optional). */\n label?: string;\n [key: string]: unknown;\n}\n\n/** A tag can be either a TaginputItem object or a plain string. */\nexport type TaginputTag = TaginputItem | string;\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n/**\n * Props for the Taginput component.\n * Inside an outer `Field`, or a `Control` with no `Field` around it, it\n * renders no `Field` of its own. The exception is `label`, `message`,\n * `horizontal` or `fieldClassName` in that bare `Control`: it keeps a `Field`\n * for them, nested in the `.control`, and warns in development. Wrap the\n * `Control` in a `Field` instead, and set the `label`, `horizontal` and class\n * name on that `Field`.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.\n */\nexport interface TaginputProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>,\n Omit<BulmaClassesProps, 'color'>,\n FormFieldProps {\n /** Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired when the tag limit is reached (the input is not rendered). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here; it then replaces the `aria-label=\"Add tag\"` fallback too. */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Applied to the inner text input (the labellable control), not the wrapper div. */\n id?: string;\n /** The current tags (controlled). */\n value?: TaginputTag[];\n /** Default tags (uncontrolled). */\n defaultValue?: TaginputTag[];\n /** Autocomplete suggestions. */\n data?: string[];\n /** Placeholder text when no tags. */\n placeholder?: string;\n /** Object property to use as display field. */\n field?: string;\n /** Allow creating new tags not in suggestions. */\n allowNew?: boolean;\n /** Allow duplicate tags. */\n allowDuplicates?: boolean;\n /** Open autocomplete dropdown on focus. */\n openOnFocus?: boolean;\n /** Remove tag on backspace. Default: true. */\n removeOnKeys?: boolean;\n /** Keys to confirm tag creation. Default: ['Enter', ',']. */\n confirmKeys?: string[];\n /** Show close button on tags. Default: true. */\n closable?: boolean;\n /** Attach tags visually. */\n attached?: boolean;\n /** Maximum number of tags allowed. */\n maxTags?: number;\n /** Maximum length of input. */\n maxlength?: number;\n /** Whether the input is disabled. */\n disabled?: boolean;\n /** Whether the input is read-only. */\n readonly?: boolean;\n /** Applies rounded corners to the tags. */\n rounded?: boolean;\n /** Truncates long tag text with ellipsis. */\n ellipsis?: boolean;\n /** Shows a counter of the number of tags. */\n hasCounter?: boolean;\n /** Characters that split pasted text into tags. */\n onPasteSeparators?: string[];\n /** Validation function called before adding a tag. */\n beforeAdding?: (tag: string) => boolean;\n /** Custom function for creating tag objects from input. */\n createTag?: (input: string) => TaginputTag;\n /** Keeps the first autocomplete suggestion highlighted. */\n keepFirst?: boolean;\n /** Keeps the autocomplete dropdown open after selection. */\n keepOpen?: boolean;\n /**\n * Shows a loading spinner in the input.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n loading?: boolean;\n /** ARIA label for tag close buttons. */\n ariaCloseLabel?: string;\n /** Icon name for the input field. */\n icon?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Input color variant. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Tag color variant. */\n tagColor?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'dark'\n | 'light';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Form field name. When set, one hidden input per tag is rendered. */\n name?: string;\n /** Optional id of the form the hidden inputs belong to. */\n form?: string;\n /** Callback when tags change. */\n onChange?: (tags: TaginputTag[]) => void;\n /** Callback when tag is added. */\n onAdd?: (tag: TaginputTag) => void;\n /** Callback when tag is removed. */\n onRemove?: (tag: TaginputTag, index: number) => void;\n /** Callback when typing in input. */\n onTyping?: (value: string) => void;\n /** Custom render for tags. */\n tagTemplate?: (tag: TaginputTag) => React.ReactNode;\n}\n\n/**\n * The `Taginput` component provides a tag/chip input field for managing multiple tags.\n *\n * @function\n * @param {TaginputProps} props - Props for the Taginput component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the input element.\n * @returns {JSX.Element} The rendered taginput component.\n *\n * @example\n * // Basic usage\n * <Taginput\n * placeholder=\"Add a tag...\"\n * onChange={(tags) => console.log(tags)}\n * />\n *\n * @example\n * // With autocomplete\n * <Taginput\n * data={['React', 'Vue', 'Angular', 'Svelte']}\n * allowNew={false}\n * placeholder=\"Select frameworks...\"\n * />\n */\nexport const Taginput = forwardRef<HTMLInputElement, TaginputProps>(\n (\n {\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n value: controlledValue,\n defaultValue = [],\n data = [],\n placeholder,\n field = 'label',\n allowNew = true,\n allowDuplicates = false,\n openOnFocus = false,\n removeOnKeys = true,\n confirmKeys = ['Enter', ','],\n closable = true,\n attached = false,\n maxTags,\n maxlength,\n disabled = false,\n readonly = false,\n rounded = false,\n ellipsis = false,\n hasCounter = true,\n onPasteSeparators = [','],\n beforeAdding,\n createTag,\n keepFirst = false,\n keepOpen = true,\n loading = false,\n ariaCloseLabel,\n icon,\n iconLibrary: iconLibraryProp,\n iconVariant,\n iconFeatures,\n color,\n tagColor,\n size,\n onChange,\n onAdd,\n onRemove,\n onTyping,\n tagTemplate,\n name,\n form,\n id,\n className,\n ...props\n },\n ref\n ) => {\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Taginput', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const { classPrefix } = useConfig();\n const defaultIconLibrary = useIconLibrary();\n const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';\n const pcn = (\n ...args: (\n | string\n | number\n | undefined\n | null\n | false\n | Record<string, unknown>\n | unknown[]\n )[]\n ) => prefixedClassNames(classPrefix, ...args);\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const [internalTags, setInternalTags] =\n useState<TaginputTag[]>(defaultValue);\n const [inputValue, setInputValue] = useState('');\n const [isActive, setIsActive] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n\n // Use controlled or internal tags\n const tags = controlledValue !== undefined ? controlledValue : internalTags;\n\n const isMaxReached = maxTags !== undefined && tags.length >= maxTags;\n // At the tag limit the text input is not rendered, so there is nothing to\n // wire a label to, its own or a surrounding Field's.\n const { controlId, fieldLabelProps, labelled } = useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel: ownField && !isMaxReached,\n hasInput: !isMaxReached,\n });\n\n // Get display value from tag\n const getDisplayValue = (tag: TaginputTag): string => {\n if (typeof tag === 'string') return tag;\n const fieldValue = tag[field];\n if (typeof fieldValue === 'string') return fieldValue;\n return tag.value || '';\n };\n\n // Filter autocomplete data\n const filteredData = data.filter(item => {\n const displayValue = item.toLowerCase();\n const matchesInput = displayValue.includes(inputValue.toLowerCase());\n const notAlreadyAdded =\n allowDuplicates ||\n !tags.some(tag => getDisplayValue(tag).toLowerCase() === displayValue);\n const hasInput = inputValue || (openOnFocus && isActive);\n return matchesInput && notAlreadyAdded && hasInput;\n });\n\n // keepFirst: auto-highlight first item when dropdown opens\n useEffect(() => {\n if (keepFirst && isActive && filteredData.length > 0) {\n setHighlightedIndex(0);\n }\n }, [keepFirst, isActive, filteredData.length]);\n\n // Update tags\n const updateTags = useCallback(\n (newTags: TaginputTag[]) => {\n if (controlledValue === undefined) {\n setInternalTags(newTags);\n }\n onChange?.(newTags);\n },\n [controlledValue, onChange]\n );\n\n // Add tag\n const addTag = useCallback(\n (value: string | TaginputTag) => {\n if (disabled || readonly) return;\n\n const tagValue = typeof value === 'string' ? value.trim() : value;\n const displayValue =\n typeof tagValue === 'string' ? tagValue : getDisplayValue(tagValue);\n\n if (!displayValue) return;\n\n // Check max tags\n if (maxTags && tags.length >= maxTags) return;\n\n // Check duplicates\n if (!allowDuplicates) {\n const exists = tags.some(\n tag =>\n getDisplayValue(tag).toLowerCase() === displayValue.toLowerCase()\n );\n if (exists) return;\n }\n\n // Check if allowed (must be in data if allowNew is false). Compare\n // case-insensitively, consistent with the dropdown filter and the\n // duplicate check above.\n if (\n !allowNew &&\n !data.some(d => d.toLowerCase() === displayValue.toLowerCase())\n )\n return;\n\n // beforeAdding validation\n if (beforeAdding && !beforeAdding(displayValue)) return;\n\n // createTag transformation\n const finalTag = createTag ? createTag(displayValue) : tagValue;\n\n const newTags = [...tags, finalTag];\n updateTags(newTags);\n onAdd?.(finalTag);\n setInputValue('');\n if (!keepOpen) {\n setIsActive(false);\n }\n setHighlightedIndex(-1);\n },\n [\n disabled,\n readonly,\n tags,\n maxTags,\n allowDuplicates,\n allowNew,\n data,\n field,\n updateTags,\n onAdd,\n beforeAdding,\n createTag,\n keepOpen,\n ]\n );\n\n // Remove tag\n const removeTag = useCallback(\n (index: number) => {\n /* istanbul ignore next: both triggers (delete button click, Backspace handler) are already gated on disabled/readonly */\n if (disabled || readonly) return;\n\n const removedTag = tags[index];\n const newTags = tags.filter((_, i) => i !== index);\n updateTags(newTags);\n onRemove?.(removedTag, index);\n },\n [disabled, readonly, tags, updateTags, onRemove]\n );\n\n // Handle input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n\n // Check if a confirm key was typed\n const lastChar = newValue.slice(-1);\n if (confirmKeys.includes(lastChar) && lastChar !== 'Enter') {\n const valueWithoutKey = newValue.slice(0, -1).trim();\n if (valueWithoutKey) {\n addTag(valueWithoutKey);\n }\n return;\n }\n\n setInputValue(newValue);\n onTyping?.(newValue);\n\n if (newValue && data.length > 0) {\n setIsActive(true);\n }\n },\n [confirmKeys, addTag, onTyping, data.length]\n );\n\n // Handle paste\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (onPasteSeparators.length === 0) return;\n\n const pastedText = e.clipboardData.getData('text');\n // Check if any separator exists in the pasted text\n const hasSeparator = onPasteSeparators.some(sep =>\n pastedText.includes(sep)\n );\n\n if (!hasSeparator) return;\n\n e.preventDefault();\n\n // Build a regex from all separators\n const escapedSeparators = onPasteSeparators.map(s =>\n s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const regex = new RegExp(`[${escapedSeparators.join('')}]`);\n\n const parts = pastedText\n .split(regex)\n .map(s => s.trim())\n .filter(Boolean);\n\n for (const part of parts) {\n addTag(part);\n }\n },\n [onPasteSeparators, addTag]\n );\n\n // Handle focus\n const handleFocus = useCallback(() => {\n if (openOnFocus && data.length > 0 && !disabled) {\n setIsActive(true);\n }\n }, [openOnFocus, data.length, disabled]);\n\n // Handle click outside\n useEffect(() => {\n if (!isActive) return undefined;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (containerRef.current && !isEventInside(e, containerRef.current)) {\n setIsActive(false);\n setHighlightedIndex(-1);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }, [isActive]);\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled || readonly) return;\n\n // Handle confirm keys\n if (confirmKeys.includes(e.key)) {\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n addTag(filteredData[highlightedIndex]);\n } else if (inputValue.trim()) {\n addTag(inputValue);\n }\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isActive && data.length > 0) {\n setIsActive(true);\n } else {\n setHighlightedIndex(prev =>\n prev < filteredData.length - 1 ? prev + 1 : prev\n );\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n setHighlightedIndex(prev => (prev > 0 ? prev - 1 : prev));\n break;\n case 'Backspace':\n if (removeOnKeys && !inputValue && tags.length > 0) {\n e.preventDefault();\n removeTag(tags.length - 1);\n }\n break;\n case 'Escape':\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n }\n },\n [\n disabled,\n readonly,\n confirmKeys,\n highlightedIndex,\n filteredData,\n addTag,\n inputValue,\n isActive,\n data.length,\n removeOnKeys,\n tags.length,\n removeTag,\n ]\n );\n\n // Combined ref\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (inputRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n }\n },\n [ref]\n );\n\n // Focus input when container is clicked\n const handleContainerClick = useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n // Generate classes\n const taginputClasses = pcn('taginput', {\n 'is-active': isActive,\n [`is-${size}`]: !!size,\n [`is-${color}`]: !!color,\n 'is-disabled': disabled,\n 'is-rounded': rounded,\n 'is-ellipsis': ellipsis,\n });\n\n const containerClasses = pcn('taginput-container', {\n 'is-attached': attached,\n 'has-icons-left': !!icon,\n });\n\n const inputClasses = pcn('input', {\n [`is-${size}`]: !!size,\n });\n\n const tagClasses = pcn('tag', {\n [`is-${tagColor}`]: !!tagColor,\n [`is-${size}`]: !!size,\n });\n\n const combinedClasses = classNames(\n taginputClasses,\n bulmaHelperClasses,\n className\n );\n\n // Counter text\n const showCounter =\n hasCounter && (maxTags !== undefined || maxlength !== undefined);\n const counterText =\n maxTags !== undefined\n ? `${tags.length} / ${maxTags}`\n : maxlength !== undefined\n ? `${inputValue.length} / ${maxlength}`\n : '';\n\n const counterClasses = pcn('help', 'counter');\n const tagsClasses = pcn('tags');\n const dropdownMenuClasses = pcn('dropdown-menu', 'is-active');\n const dropdownContentClasses = pcn('dropdown-content');\n const iconRightClass = pcn('icon', 'is-right');\n const loaderClass = pcn('loader', 'is-loading');\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n const taginputElement = (\n <div\n ref={containerRef}\n className={combinedClasses}\n onClick={handleContainerClick}\n {...rest}\n >\n <div className={containerClasses}>\n {icon && (\n <Icon\n name={icon}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n containerClassName={pcn('icon', 'is-left')}\n />\n )}\n <div className={tagsClasses}>\n {tags.map((tag, index) => {\n const displayVal = getDisplayValue(tag);\n return (\n <span key={index} className={tagClasses}>\n {tagTemplate ? (\n tagTemplate(tag)\n ) : ellipsis ? (\n <span title={displayVal}>{displayVal}</span>\n ) : (\n displayVal\n )}\n {closable && !disabled && !readonly && (\n <button\n type=\"button\"\n className={pcn('delete', 'is-small')}\n onClick={e => {\n e.stopPropagation();\n removeTag(index);\n }}\n aria-label={ariaCloseLabel || `Remove ${displayVal}`}\n />\n )}\n </span>\n );\n })}\n {!isMaxReached && (\n <input\n ref={combinedRef}\n type=\"text\"\n className={inputClasses}\n id={controlId}\n value={inputValue}\n placeholder={tags.length === 0 ? placeholder : undefined}\n disabled={disabled}\n readOnly={readonly}\n maxLength={maxlength}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n // Fallback name, dropped only when a rendered label actually\n // targets this input, its own or a surrounding Field's\n // (aria-label would win otherwise). A label pointing elsewhere\n // keeps the fallback so the input is never nameless.\n aria-label={labelled ? undefined : 'Add tag'}\n />\n )}\n </div>\n {loading && (\n <span className={iconRightClass}>\n <span className={loaderClass} />\n </span>\n )}\n </div>\n\n {isActive && filteredData.length > 0 && (\n <div className={dropdownMenuClasses}>\n <div\n ref={dropdownRef}\n className={dropdownContentClasses}\n role=\"listbox\"\n >\n {filteredData.map((item, index) => (\n <a\n key={index}\n className={pcn('dropdown-item', {\n 'is-active': index === highlightedIndex,\n })}\n onClick={() => addTag(item)}\n onMouseEnter={() => setHighlightedIndex(index)}\n role=\"option\"\n aria-selected={index === highlightedIndex}\n >\n {item}\n </a>\n ))}\n </div>\n </div>\n )}\n\n {showCounter && <small className={counterClasses}>{counterText}</small>}\n\n {name &&\n tags.map((tag, i) => (\n <input\n key={`tag-input-${i}`}\n type=\"hidden\"\n name={name}\n value={getDisplayValue(tag)}\n form={form}\n />\n ))}\n </div>\n );\n\n if (ownField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {taginputElement}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {taginputElement}\n {messageEl}\n </>\n );\n }\n);\n\nTaginput.displayName = 'Taginput';\n\n/** @deprecated Use `Taginput` — same component. */\nexport const TagInput = Taginput;\n\n/** @deprecated Use `TaginputProps`. */\nexport type TagInputProps = TaginputProps;\n\nexport default Taginput;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Taginput.js","sources":["../../../src/form/Taginput.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useState,\n useRef,\n useEffect,\n useCallback,\n useId,\n} from 'react';\nimport {\n classNames,\n usePrefixedClassNames,\n prefixedClassNames,\n} from '../helpers/classNames';\nimport { useConfig, useIconLibrary } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { isEventInside } from '../helpers/shadowDom';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n} from './FormContext';\nimport { Field } from './Field';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelId } from './useAutoLabelId';\nimport { Icon } from '../elements/Icon';\n\n/**\n * Represents a tag item object with a value and optional label.\n */\nexport interface TaginputItem {\n /** The tag value. */\n value: string;\n /** Display label (optional). */\n label?: string;\n [key: string]: unknown;\n}\n\n/** A tag can be either a TaginputItem object or a plain string. */\nexport type TaginputTag = TaginputItem | string;\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n/**\n * Props for the Taginput component.\n * Inside an outer `Field`, or a `Control` with no `Field` around it, it\n * renders no `Field` of its own. The exception is `label`, `message`,\n * `horizontal` or `fieldClassName` in that bare `Control`: it keeps a `Field`\n * for them, nested in the `.control`, and warns in development. Wrap the\n * `Control` in a `Field` instead, and set the `label`, `horizontal` and class\n * name on that `Field`.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.\n */\nexport interface TaginputProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>,\n Omit<BulmaClassesProps, 'color'>,\n FormFieldProps {\n /** Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired when the tag limit is reached (the input is not rendered). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here; it then replaces the `aria-label=\"Add tag\"` fallback too. With `data`, the label naming the input also names the open suggestion list, through `aria-labelledby`, when it has an id: this label always does, and an outer `Field`'s does unless you wired it by hand without an `id` in its `labelProps`. Otherwise the list is named \"Suggestions\". */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). With `data`, while the label names the input, the suggestion list's `aria-labelledby` points at it, through an `id` here when you give one and a generated one otherwise. */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Applied to the inner text input (the labellable control), not the wrapper div. */\n id?: string;\n /** The current tags (controlled). */\n value?: TaginputTag[];\n /** Default tags (uncontrolled). */\n defaultValue?: TaginputTag[];\n /**\n * Autocomplete suggestions. With `data` set, even to an empty array, the\n * text input is a `role=\"combobox\"` that controls the suggestion list and\n * points `aria-activedescendant` at the highlighted suggestion. Without it\n * there's no list, so the input stays a plain text field.\n */\n data?: string[];\n /** Placeholder text when no tags. */\n placeholder?: string;\n /** Object property to use as display field. */\n field?: string;\n /** Allow creating new tags not in suggestions. */\n allowNew?: boolean;\n /** Allow duplicate tags. */\n allowDuplicates?: boolean;\n /** Open autocomplete dropdown on focus. */\n openOnFocus?: boolean;\n /** Remove tag on backspace. Default: true. */\n removeOnKeys?: boolean;\n /** Keys to confirm tag creation. Default: ['Enter', ',']. */\n confirmKeys?: string[];\n /** Show close button on tags. Default: true. */\n closable?: boolean;\n /** Attach tags visually. */\n attached?: boolean;\n /** Maximum number of tags allowed. */\n maxTags?: number;\n /** Maximum length of input. */\n maxlength?: number;\n /** Whether the input is disabled. */\n disabled?: boolean;\n /** Whether the input is read-only. */\n readonly?: boolean;\n /** Applies rounded corners to the tags. */\n rounded?: boolean;\n /** Truncates long tag text with ellipsis. */\n ellipsis?: boolean;\n /** Shows a counter of the number of tags. */\n hasCounter?: boolean;\n /** Characters that split pasted text into tags. */\n onPasteSeparators?: string[];\n /** Validation function called before adding a tag. */\n beforeAdding?: (tag: string) => boolean;\n /** Custom function for creating tag objects from input. */\n createTag?: (input: string) => TaginputTag;\n /** Keeps the first autocomplete suggestion highlighted. */\n keepFirst?: boolean;\n /** Keeps the autocomplete dropdown open after selection. */\n keepOpen?: boolean;\n /**\n * Shows a loading spinner in the input.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n loading?: boolean;\n /** ARIA label for tag close buttons. */\n ariaCloseLabel?: string;\n /** Icon name for the input field. */\n icon?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Input color variant. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Tag color variant. */\n tagColor?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'dark'\n | 'light';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Form field name. When set, one hidden input per tag is rendered. */\n name?: string;\n /** Optional id of the form the hidden inputs belong to. */\n form?: string;\n /** Callback when tags change. */\n onChange?: (tags: TaginputTag[]) => void;\n /** Callback when tag is added. */\n onAdd?: (tag: TaginputTag) => void;\n /** Callback when tag is removed. */\n onRemove?: (tag: TaginputTag, index: number) => void;\n /** Callback when typing in input. */\n onTyping?: (value: string) => void;\n /** Custom render for tags. */\n tagTemplate?: (tag: TaginputTag) => React.ReactNode;\n}\n\n/**\n * The `Taginput` component provides a tag/chip input field for managing multiple tags.\n *\n * @function\n * @param {TaginputProps} props - Props for the Taginput component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the input element.\n * @returns {JSX.Element} The rendered taginput component.\n *\n * @example\n * // Basic usage\n * <Taginput\n * placeholder=\"Add a tag...\"\n * onChange={(tags) => console.log(tags)}\n * />\n *\n * @example\n * // With autocomplete\n * <Taginput\n * data={['React', 'Vue', 'Angular', 'Svelte']}\n * allowNew={false}\n * placeholder=\"Select frameworks...\"\n * />\n */\nexport const Taginput = forwardRef<HTMLInputElement, TaginputProps>(\n (\n {\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n value: controlledValue,\n defaultValue = [],\n data: dataProp,\n placeholder,\n field = 'label',\n allowNew = true,\n allowDuplicates = false,\n openOnFocus = false,\n removeOnKeys = true,\n confirmKeys = ['Enter', ','],\n closable = true,\n attached = false,\n maxTags,\n maxlength,\n disabled = false,\n readonly = false,\n rounded = false,\n ellipsis = false,\n hasCounter = true,\n onPasteSeparators = [','],\n beforeAdding,\n createTag,\n keepFirst = false,\n keepOpen = true,\n loading = false,\n ariaCloseLabel,\n icon,\n iconLibrary: iconLibraryProp,\n iconVariant,\n iconFeatures,\n color,\n tagColor,\n size,\n onChange,\n onAdd,\n onRemove,\n onTyping,\n tagTemplate,\n name,\n form,\n id,\n className,\n ...props\n },\n ref\n ) => {\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Taginput', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const { classPrefix } = useConfig();\n const defaultIconLibrary = useIconLibrary();\n const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';\n const pcn = (\n ...args: (\n | string\n | number\n | undefined\n | null\n | false\n | Record<string, unknown>\n | unknown[]\n )[]\n ) => prefixedClassNames(classPrefix, ...args);\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const [internalTags, setInternalTags] =\n useState<TaginputTag[]>(defaultValue);\n const [inputValue, setInputValue] = useState('');\n const [isActive, setIsActive] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const listboxId = `${useId()}-listbox`;\n\n // With `data` the input offers suggestions, so it's a combobox, even\n // while none match. Without it there's never a list, so it stays a plain\n // text field.\n const hasSuggestions = dataProp !== undefined;\n const data = dataProp ?? [];\n\n // Use controlled or internal tags\n const tags = controlledValue !== undefined ? controlledValue : internalTags;\n\n const isMaxReached = maxTags !== undefined && tags.length >= maxTags;\n // At the tag limit the text input is not rendered, so there is nothing to\n // wire a label to, its own or a surrounding Field's. The suggestion list\n // points `aria-labelledby` at the label that names the input, so with\n // suggestions it needs that label's id.\n const {\n controlId,\n fieldLabelProps,\n labelled,\n labelId: listLabelId,\n } = useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel: ownField && !isMaxReached,\n hasInput: !isMaxReached,\n needsLabelId: hasSuggestions,\n });\n\n // Get display value from tag\n const getDisplayValue = (tag: TaginputTag): string => {\n if (typeof tag === 'string') return tag;\n const fieldValue = tag[field];\n if (typeof fieldValue === 'string') return fieldValue;\n return tag.value || '';\n };\n\n // Filter autocomplete data\n const filteredData = data.filter(item => {\n const displayValue = item.toLowerCase();\n const matchesInput = displayValue.includes(inputValue.toLowerCase());\n const notAlreadyAdded =\n allowDuplicates ||\n !tags.some(tag => getDisplayValue(tag).toLowerCase() === displayValue);\n const hasInput = inputValue || (openOnFocus && isActive);\n return matchesInput && notAlreadyAdded && hasInput;\n });\n const listOpen = isActive && filteredData.length > 0;\n\n // keepFirst: auto-highlight first item when dropdown opens\n useEffect(() => {\n if (keepFirst && isActive && filteredData.length > 0) {\n setHighlightedIndex(0);\n }\n }, [keepFirst, isActive, filteredData.length]);\n\n // Update tags\n const updateTags = useCallback(\n (newTags: TaginputTag[]) => {\n if (controlledValue === undefined) {\n setInternalTags(newTags);\n }\n onChange?.(newTags);\n },\n [controlledValue, onChange]\n );\n\n // Add tag\n const addTag = useCallback(\n (value: string | TaginputTag) => {\n if (disabled || readonly) return;\n\n const tagValue = typeof value === 'string' ? value.trim() : value;\n const displayValue =\n typeof tagValue === 'string' ? tagValue : getDisplayValue(tagValue);\n\n if (!displayValue) return;\n\n // Check max tags\n if (maxTags && tags.length >= maxTags) return;\n\n // Check duplicates\n if (!allowDuplicates) {\n const exists = tags.some(\n tag =>\n getDisplayValue(tag).toLowerCase() === displayValue.toLowerCase()\n );\n if (exists) return;\n }\n\n // Check if allowed (must be in data if allowNew is false). Compare\n // case-insensitively, consistent with the dropdown filter and the\n // duplicate check above.\n if (\n !allowNew &&\n !data.some(d => d.toLowerCase() === displayValue.toLowerCase())\n )\n return;\n\n // beforeAdding validation\n if (beforeAdding && !beforeAdding(displayValue)) return;\n\n // createTag transformation\n const finalTag = createTag ? createTag(displayValue) : tagValue;\n\n const newTags = [...tags, finalTag];\n updateTags(newTags);\n onAdd?.(finalTag);\n setInputValue('');\n if (!keepOpen) {\n setIsActive(false);\n }\n setHighlightedIndex(-1);\n },\n [\n disabled,\n readonly,\n tags,\n maxTags,\n allowDuplicates,\n allowNew,\n data,\n field,\n updateTags,\n onAdd,\n beforeAdding,\n createTag,\n keepOpen,\n ]\n );\n\n // Remove tag\n const removeTag = useCallback(\n (index: number) => {\n /* istanbul ignore next: both triggers (delete button click, Backspace handler) are already gated on disabled/readonly */\n if (disabled || readonly) return;\n\n const removedTag = tags[index];\n const newTags = tags.filter((_, i) => i !== index);\n updateTags(newTags);\n onRemove?.(removedTag, index);\n },\n [disabled, readonly, tags, updateTags, onRemove]\n );\n\n // Handle input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n\n // Check if a confirm key was typed\n const lastChar = newValue.slice(-1);\n if (confirmKeys.includes(lastChar) && lastChar !== 'Enter') {\n const valueWithoutKey = newValue.slice(0, -1).trim();\n if (valueWithoutKey) {\n addTag(valueWithoutKey);\n }\n return;\n }\n\n setInputValue(newValue);\n onTyping?.(newValue);\n\n if (newValue && data.length > 0) {\n setIsActive(true);\n }\n },\n [confirmKeys, addTag, onTyping, data.length]\n );\n\n // Handle paste\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (onPasteSeparators.length === 0) return;\n\n const pastedText = e.clipboardData.getData('text');\n // Check if any separator exists in the pasted text\n const hasSeparator = onPasteSeparators.some(sep =>\n pastedText.includes(sep)\n );\n\n if (!hasSeparator) return;\n\n e.preventDefault();\n\n // Build a regex from all separators\n const escapedSeparators = onPasteSeparators.map(s =>\n s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const regex = new RegExp(`[${escapedSeparators.join('')}]`);\n\n const parts = pastedText\n .split(regex)\n .map(s => s.trim())\n .filter(Boolean);\n\n for (const part of parts) {\n addTag(part);\n }\n },\n [onPasteSeparators, addTag]\n );\n\n // Handle focus\n const handleFocus = useCallback(() => {\n if (openOnFocus && data.length > 0 && !disabled) {\n setIsActive(true);\n }\n }, [openOnFocus, data.length, disabled]);\n\n // Handle click outside\n useEffect(() => {\n if (!isActive) return undefined;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (containerRef.current && !isEventInside(e, containerRef.current)) {\n setIsActive(false);\n setHighlightedIndex(-1);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }, [isActive]);\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled || readonly) return;\n\n // Handle confirm keys\n if (confirmKeys.includes(e.key)) {\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n addTag(filteredData[highlightedIndex]);\n } else if (inputValue.trim()) {\n addTag(inputValue);\n }\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isActive && data.length > 0) {\n setIsActive(true);\n } else {\n setHighlightedIndex(prev =>\n prev < filteredData.length - 1 ? prev + 1 : prev\n );\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n setHighlightedIndex(prev => (prev > 0 ? prev - 1 : prev));\n break;\n case 'Backspace':\n if (removeOnKeys && !inputValue && tags.length > 0) {\n e.preventDefault();\n removeTag(tags.length - 1);\n }\n break;\n case 'Escape':\n // Closing the suggestions claims the key, so a Modal around the\n // field stays open. With none showing, the key goes on to it.\n if (isActive && filteredData.length > 0) e.preventDefault();\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n }\n },\n [\n disabled,\n readonly,\n confirmKeys,\n highlightedIndex,\n filteredData,\n addTag,\n inputValue,\n isActive,\n data.length,\n removeOnKeys,\n tags.length,\n removeTag,\n ]\n );\n\n // Combined ref\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (inputRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n }\n },\n [ref]\n );\n\n // Focus input when container is clicked\n const handleContainerClick = useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n // Generate classes\n const taginputClasses = pcn('taginput', {\n 'is-active': isActive,\n [`is-${size}`]: !!size,\n [`is-${color}`]: !!color,\n 'is-disabled': disabled,\n 'is-rounded': rounded,\n 'is-ellipsis': ellipsis,\n });\n\n const containerClasses = pcn('taginput-container', {\n 'is-attached': attached,\n 'has-icons-left': !!icon,\n });\n\n const inputClasses = pcn('input', {\n [`is-${size}`]: !!size,\n });\n\n const tagClasses = pcn('tag', {\n [`is-${tagColor}`]: !!tagColor,\n [`is-${size}`]: !!size,\n });\n\n const combinedClasses = classNames(\n taginputClasses,\n bulmaHelperClasses,\n className\n );\n\n // Counter text\n const showCounter =\n hasCounter && (maxTags !== undefined || maxlength !== undefined);\n const counterText =\n maxTags !== undefined\n ? `${tags.length} / ${maxTags}`\n : maxlength !== undefined\n ? `${inputValue.length} / ${maxlength}`\n : '';\n\n const counterClasses = pcn('help', 'counter');\n const tagsClasses = pcn('tags');\n const dropdownMenuClasses = pcn('dropdown-menu', 'is-active');\n const dropdownContentClasses = pcn('dropdown-content');\n const iconRightClass = pcn('icon', 'is-right');\n const loaderClass = pcn('loader', 'is-loading');\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n // The combobox controls its listbox and points at the highlighted option,\n // the way Autocomplete's does. The listbox takes its name from the label\n // that names the combobox, the one this renders or a surrounding Field's,\n // and keeps a fallback name when no label names it or the one that does\n // has no id to point at. While no suggestion matches there's no listbox,\n // so the combobox is collapsed and points at nothing. It skips a\n // highlighted suggestion that's blank once trimmed, since that one can't\n // become a tag, and the option it points at is the one marked selected.\n const optionId = (index: number) => `${listboxId}-${index}`;\n const activeOptionId =\n listOpen && filteredData[highlightedIndex]?.trim()\n ? optionId(highlightedIndex)\n : undefined;\n const comboboxProps: React.InputHTMLAttributes<HTMLInputElement> = {\n role: 'combobox',\n 'aria-expanded': listOpen,\n 'aria-controls': listOpen ? listboxId : undefined,\n 'aria-activedescendant': activeOptionId,\n 'aria-haspopup': 'listbox',\n 'aria-autocomplete': 'list',\n };\n\n const taginputElement = (\n <div\n ref={containerRef}\n className={combinedClasses}\n onClick={handleContainerClick}\n {...rest}\n >\n <div className={containerClasses}>\n {icon && (\n <Icon\n name={icon}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n containerClassName={pcn('icon', 'is-left')}\n />\n )}\n <div className={tagsClasses}>\n {tags.map((tag, index) => {\n const displayVal = getDisplayValue(tag);\n return (\n <span key={index} className={tagClasses}>\n {tagTemplate ? (\n tagTemplate(tag)\n ) : ellipsis ? (\n <span title={displayVal}>{displayVal}</span>\n ) : (\n displayVal\n )}\n {closable && !disabled && !readonly && (\n <button\n type=\"button\"\n className={pcn('delete', 'is-small')}\n onClick={e => {\n e.stopPropagation();\n removeTag(index);\n }}\n aria-label={ariaCloseLabel || `Remove ${displayVal}`}\n />\n )}\n </span>\n );\n })}\n {!isMaxReached && (\n <input\n ref={combinedRef}\n type=\"text\"\n className={inputClasses}\n id={controlId}\n value={inputValue}\n placeholder={tags.length === 0 ? placeholder : undefined}\n disabled={disabled}\n readOnly={readonly}\n maxLength={maxlength}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n {...(hasSuggestions && comboboxProps)}\n // Fallback name, dropped only when a rendered label actually\n // targets this input, its own or a surrounding Field's\n // (aria-label would win otherwise). A label pointing elsewhere\n // keeps the fallback so the input is never nameless.\n aria-label={labelled ? undefined : 'Add tag'}\n />\n )}\n </div>\n {loading && (\n <span className={iconRightClass}>\n <span className={loaderClass} />\n </span>\n )}\n </div>\n\n {listOpen && (\n <div className={dropdownMenuClasses}>\n <div\n ref={dropdownRef}\n id={listboxId}\n className={dropdownContentClasses}\n role=\"listbox\"\n aria-labelledby={listLabelId}\n aria-label={listLabelId ? undefined : 'Suggestions'}\n >\n {filteredData.map((item, index) => (\n <a\n key={index}\n id={optionId(index)}\n className={pcn('dropdown-item', {\n 'is-active': index === highlightedIndex,\n })}\n onClick={() => addTag(item)}\n onMouseEnter={() => setHighlightedIndex(index)}\n role=\"option\"\n aria-selected={optionId(index) === activeOptionId}\n >\n {item}\n </a>\n ))}\n </div>\n </div>\n )}\n\n {showCounter && <small className={counterClasses}>{counterText}</small>}\n\n {name &&\n tags.map((tag, i) => (\n <input\n key={`tag-input-${i}`}\n type=\"hidden\"\n name={name}\n value={getDisplayValue(tag)}\n form={form}\n />\n ))}\n </div>\n );\n\n if (ownField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {taginputElement}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {taginputElement}\n {messageEl}\n </>\n );\n }\n);\n\nTaginput.displayName = 'Taginput';\n\n/** @deprecated Use `Taginput` — same component. */\nexport const TagInput = Taginput;\n\n/** @deprecated Use `TaginputProps`. */\nexport type TagInputProps = TaginputProps;\n\nexport default Taginput;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import { createPortal } from 'react-dom';
|
|
|
5
5
|
import { usePrefixedClassNames, classNames } from '../../helpers/classNames.js';
|
|
6
6
|
import { useFocusTrap } from '../../helpers/useFocusTrap.js';
|
|
7
7
|
import { usePortalContainer } from '../../helpers/portal.js';
|
|
8
|
+
import { isEventInside } from '../../helpers/shadowDom.js';
|
|
8
9
|
import { useAnchoredPosition, marginGap } from '../../helpers/useAnchoredPosition.js';
|
|
9
10
|
|
|
10
11
|
const isBrowser = typeof window !== 'undefined';
|
|
@@ -48,13 +49,20 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'botto
|
|
|
48
49
|
return () => document.removeEventListener('pointerdown', handler);
|
|
49
50
|
}, [isOpen, closeOnClickOutside, anchorRef, onClose]);
|
|
50
51
|
// Escape closes it, and so does Alt+ArrowUp, the combobox's key for it,
|
|
51
|
-
// which the calendar and the time wheels inside leave to it.
|
|
52
|
+
// which the calendar and the time wheels inside leave to it. Escape closes
|
|
53
|
+
// it from anywhere, but the key is only the picker's when it was pressed in
|
|
54
|
+
// the panel or the field: then it's marked used, so a Modal or Sidebar
|
|
55
|
+
// around the picker stays open. From anywhere else, such as a dialog opened
|
|
56
|
+
// over the picker, the key goes on to whatever has focus.
|
|
52
57
|
useEffect(() => {
|
|
53
58
|
if (!isOpen || !closeOnEscape || !isBrowser)
|
|
54
59
|
return undefined;
|
|
55
60
|
const handler = (e) => {
|
|
56
61
|
if (e.key === 'Escape') {
|
|
57
|
-
e.
|
|
62
|
+
if (isEventInside(e, panelRef.current) ||
|
|
63
|
+
isEventInside(e, anchorRef.current)) {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
}
|
|
58
66
|
onClose();
|
|
59
67
|
}
|
|
60
68
|
else if (e.altKey && e.key === 'ArrowUp') {
|
|
@@ -65,7 +73,7 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'botto
|
|
|
65
73
|
};
|
|
66
74
|
document.addEventListener('keydown', handler);
|
|
67
75
|
return () => document.removeEventListener('keydown', handler);
|
|
68
|
-
}, [isOpen, closeOnEscape, onClose]);
|
|
76
|
+
}, [isOpen, closeOnEscape, anchorRef, onClose]);
|
|
69
77
|
useFocusTrap(panelRef, {
|
|
70
78
|
active: isOpen && trapFocus,
|
|
71
79
|
initialFocusRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickerPopover.js","sources":["../../../../src/form/_pickerInternals/PickerPopover.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { classNames, usePrefixedClassNames } from '../../helpers/classNames';\nimport { useFocusTrap } from '../../helpers/useFocusTrap';\nimport { usePortalContainer } from '../../helpers/portal';\nimport {\n marginGap,\n useAnchoredPosition,\n} from '../../helpers/useAnchoredPosition';\nimport { PickerPosition } from './pickerTypes';\n\nexport interface PickerPopoverProps {\n isOpen: boolean;\n onClose: () => void;\n anchorRef: React.RefObject<HTMLElement | null>;\n children: React.ReactNode;\n position?: PickerPosition;\n appendToBody?: boolean;\n className?: string;\n trapFocus?: boolean;\n closeOnClickOutside?: boolean;\n /** Close on Escape and on Alt+ArrowUp. Default `true`. */\n closeOnEscape?: boolean;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n role?: 'dialog' | 'group';\n id?: string;\n /**\n * Where focus goes when the popover closes. Without it, focus goes back to\n * whatever had it when the focus trap turned on, which is read after the\n * panel's content mounts: a calendar that focuses a cell as it mounts\n * would be recorded instead, and that cell leaves with the panel.\n */\n restoreFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * Selects the element in the panel that takes focus as it opens, such as a\n * calendar's focused date rather than the first button in its header. When\n * nothing matches, or the match can't take focus, the first tab stop does.\n */\n initialFocusSelector?: string;\n}\n\nconst isBrowser = typeof window !== 'undefined';\n\nexport const PickerPopover: React.FC<PickerPopoverProps> = ({\n isOpen,\n onClose,\n anchorRef,\n children,\n position = 'bottom-left',\n appendToBody = false,\n className,\n trapFocus = true,\n closeOnClickOutside = true,\n closeOnEscape = true,\n ariaLabel,\n ariaLabelledBy,\n role = 'dialog',\n id,\n restoreFocusRef,\n initialFocusSelector,\n}) => {\n const panelRef = useRef<HTMLDivElement>(null);\n const resolveContainer = usePortalContainer();\n // Read as the trap turns on, once the panel's content has rendered.\n const initialFocusRef = useMemo(\n () =>\n initialFocusSelector === undefined\n ? undefined\n : {\n get current() {\n return (\n panelRef.current?.querySelector<HTMLElement>(\n initialFocusSelector\n ) ?? null\n );\n },\n },\n [initialFocusSelector]\n );\n const resolved = useAnchoredPosition(anchorRef, panelRef, {\n active: isOpen,\n position,\n fixed: appendToBody,\n // The gap comes from `--bulma-picker-popover-offset` as a margin, in place\n // or portaled, so the coordinates leave it out and `auto` reads it off\n // the panel.\n offset: 0,\n styledGap: marginGap,\n });\n\n useEffect(() => {\n if (!isOpen || !closeOnClickOutside || !isBrowser) return undefined;\n // Listen on `pointerdown` (rather than `mousedown`) so touch starts\n // outside the popover dismiss it on mobile — including swipe-from-outside\n // gestures, where the synthetic mouse event would otherwise lag a few\n // hundred ms behind the actual touch.\n const handler = (e: PointerEvent) => {\n const path = e.composedPath();\n if (panelRef.current && path.includes(panelRef.current)) return;\n if (anchorRef.current && path.includes(anchorRef.current)) return;\n onClose();\n };\n document.addEventListener('pointerdown', handler);\n return () => document.removeEventListener('pointerdown', handler);\n }, [isOpen, closeOnClickOutside, anchorRef, onClose]);\n\n // Escape closes it, and so does Alt+ArrowUp, the combobox's key for it,\n // which the calendar and the time wheels inside leave to it.\n useEffect(() => {\n if (!isOpen || !closeOnEscape || !isBrowser) return undefined;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.
|
|
1
|
+
{"version":3,"file":"PickerPopover.js","sources":["../../../../src/form/_pickerInternals/PickerPopover.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { classNames, usePrefixedClassNames } from '../../helpers/classNames';\nimport { useFocusTrap } from '../../helpers/useFocusTrap';\nimport { usePortalContainer } from '../../helpers/portal';\nimport { isEventInside } from '../../helpers/shadowDom';\nimport {\n marginGap,\n useAnchoredPosition,\n} from '../../helpers/useAnchoredPosition';\nimport { PickerPosition } from './pickerTypes';\n\nexport interface PickerPopoverProps {\n isOpen: boolean;\n onClose: () => void;\n anchorRef: React.RefObject<HTMLElement | null>;\n children: React.ReactNode;\n position?: PickerPosition;\n appendToBody?: boolean;\n className?: string;\n trapFocus?: boolean;\n closeOnClickOutside?: boolean;\n /** Close on Escape and on Alt+ArrowUp. Default `true`. */\n closeOnEscape?: boolean;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n role?: 'dialog' | 'group';\n id?: string;\n /**\n * Where focus goes when the popover closes. Without it, focus goes back to\n * whatever had it when the focus trap turned on, which is read after the\n * panel's content mounts: a calendar that focuses a cell as it mounts\n * would be recorded instead, and that cell leaves with the panel.\n */\n restoreFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * Selects the element in the panel that takes focus as it opens, such as a\n * calendar's focused date rather than the first button in its header. When\n * nothing matches, or the match can't take focus, the first tab stop does.\n */\n initialFocusSelector?: string;\n}\n\nconst isBrowser = typeof window !== 'undefined';\n\nexport const PickerPopover: React.FC<PickerPopoverProps> = ({\n isOpen,\n onClose,\n anchorRef,\n children,\n position = 'bottom-left',\n appendToBody = false,\n className,\n trapFocus = true,\n closeOnClickOutside = true,\n closeOnEscape = true,\n ariaLabel,\n ariaLabelledBy,\n role = 'dialog',\n id,\n restoreFocusRef,\n initialFocusSelector,\n}) => {\n const panelRef = useRef<HTMLDivElement>(null);\n const resolveContainer = usePortalContainer();\n // Read as the trap turns on, once the panel's content has rendered.\n const initialFocusRef = useMemo(\n () =>\n initialFocusSelector === undefined\n ? undefined\n : {\n get current() {\n return (\n panelRef.current?.querySelector<HTMLElement>(\n initialFocusSelector\n ) ?? null\n );\n },\n },\n [initialFocusSelector]\n );\n const resolved = useAnchoredPosition(anchorRef, panelRef, {\n active: isOpen,\n position,\n fixed: appendToBody,\n // The gap comes from `--bulma-picker-popover-offset` as a margin, in place\n // or portaled, so the coordinates leave it out and `auto` reads it off\n // the panel.\n offset: 0,\n styledGap: marginGap,\n });\n\n useEffect(() => {\n if (!isOpen || !closeOnClickOutside || !isBrowser) return undefined;\n // Listen on `pointerdown` (rather than `mousedown`) so touch starts\n // outside the popover dismiss it on mobile — including swipe-from-outside\n // gestures, where the synthetic mouse event would otherwise lag a few\n // hundred ms behind the actual touch.\n const handler = (e: PointerEvent) => {\n const path = e.composedPath();\n if (panelRef.current && path.includes(panelRef.current)) return;\n if (anchorRef.current && path.includes(anchorRef.current)) return;\n onClose();\n };\n document.addEventListener('pointerdown', handler);\n return () => document.removeEventListener('pointerdown', handler);\n }, [isOpen, closeOnClickOutside, anchorRef, onClose]);\n\n // Escape closes it, and so does Alt+ArrowUp, the combobox's key for it,\n // which the calendar and the time wheels inside leave to it. Escape closes\n // it from anywhere, but the key is only the picker's when it was pressed in\n // the panel or the field: then it's marked used, so a Modal or Sidebar\n // around the picker stays open. From anywhere else, such as a dialog opened\n // over the picker, the key goes on to whatever has focus.\n useEffect(() => {\n if (!isOpen || !closeOnEscape || !isBrowser) return undefined;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n if (\n isEventInside(e, panelRef.current) ||\n isEventInside(e, anchorRef.current)\n ) {\n e.preventDefault();\n }\n onClose();\n } else if (e.altKey && e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n onClose();\n }\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [isOpen, closeOnEscape, anchorRef, onClose]);\n\n useFocusTrap(panelRef, {\n active: isOpen && trapFocus,\n initialFocusRef,\n restoreFocus: restoreFocusRef ?? true,\n });\n\n const panelClass = usePrefixedClassNames('picker-popover', {\n 'is-active': isOpen,\n [`is-${resolved.position}`]: true,\n 'is-portal': appendToBody,\n });\n\n if (!isOpen) return null;\n\n const style: React.CSSProperties = appendToBody\n ? {\n position: 'fixed',\n top: resolved.top,\n left: resolved.left,\n }\n : {};\n\n const panel = (\n <div\n ref={panelRef}\n id={id}\n role={role}\n aria-modal={role === 'dialog' ? 'false' : undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n tabIndex={-1}\n className={classNames(panelClass, className)}\n style={style}\n >\n {children}\n </div>\n );\n\n if (appendToBody && isBrowser) {\n return createPortal(panel, resolveContainer());\n }\n return panel;\n};\n\nPickerPopover.displayName = 'PickerPopover';\n\nexport default PickerPopover;\n"],"names":["_jsx"],"mappings":"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"}
|
|
@@ -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 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;;"}
|
|
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 and Taginput's\n * suggestion lists (#998, #1082) 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;;"}
|