@allxsmith/bestax-bulma 5.57.1 → 5.57.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/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/Toast.js +21 -7
- package/dist/esm/components/Toast.js.map +1 -1
- package/dist/esm/elements/Tr.js.map +1 -1
- package/dist/esm/form/Checkbox.js +21 -14
- package/dist/esm/form/Checkbox.js.map +1 -1
- package/dist/esm/form/CheckboxCard.js +17 -11
- package/dist/esm/form/CheckboxCard.js.map +1 -1
- package/dist/esm/form/Checkboxes.js +30 -3
- package/dist/esm/form/Checkboxes.js.map +1 -1
- package/dist/esm/form/FormContext.js +31 -1
- package/dist/esm/form/FormContext.js.map +1 -1
- package/dist/esm/form/Radio.js +13 -10
- package/dist/esm/form/Radio.js.map +1 -1
- package/dist/esm/form/RadioCard.js +10 -8
- package/dist/esm/form/RadioCard.js.map +1 -1
- package/dist/esm/form/Radios.js +15 -3
- package/dist/esm/form/Radios.js.map +1 -1
- package/dist/esm/form/Rate.js +2 -2
- package/dist/esm/form/Rate.js.map +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +152 -52
- package/dist/index.cjs.map +1 -1
- package/dist/types/components/Toast.d.ts +14 -3
- package/dist/types/elements/Tr.d.ts +3 -3
- package/dist/types/form/CheckboxCard.d.ts +1 -1
- package/dist/types/form/Checkboxes.d.ts +7 -1
- package/dist/types/form/FormContext.d.ts +34 -1
- package/dist/types/form/RadioCard.d.ts +1 -1
- package/dist/types/form/Radios.d.ts +5 -1
- package/dist/types/form/Rate.d.ts +5 -1
- package/dist/types-cjs/components/Toast.d.ts +14 -3
- package/dist/types-cjs/elements/Tr.d.ts +3 -3
- package/dist/types-cjs/form/CheckboxCard.d.ts +1 -1
- package/dist/types-cjs/form/Checkboxes.d.ts +7 -1
- package/dist/types-cjs/form/FormContext.d.ts +34 -1
- package/dist/types-cjs/form/RadioCard.d.ts +1 -1
- package/dist/types-cjs/form/Radios.d.ts +5 -1
- package/dist/types-cjs/form/Rate.d.ts +5 -1
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/CLAUDE.md +4 -1
- package/src/scss/_selected-row.scss +43 -0
- package/src/scss/components/_index.scss +1 -0
- package/src/scss/components/_pagination.scss +25 -0
- package/src/scss/components/_toast.scss +2 -1
- package/src/scss/form/_checkbox.scss +18 -42
- package/src/scss/form/_combobox.scss +11 -0
- package/src/scss/form/_radio.scss +28 -2
- package/src/scss/form/_switch.scss +9 -5
- package/src/scss/form/_taginput.scss +6 -2
|
@@ -4,7 +4,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import { forwardRef, useState, useRef, useCallback, useEffect, useSyncExternalStore } from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { isEventInside } from '../helpers/shadowDom.js';
|
|
7
|
-
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
7
|
+
import { usePrefixedClassNames, classNames, prefixedClassNames } from '../helpers/classNames.js';
|
|
8
|
+
import { useClassPrefix } from '../helpers/Config.js';
|
|
8
9
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
9
10
|
import { usePortalContainer } from '../helpers/portal.js';
|
|
10
11
|
import { LocalePortalScope } from '../helpers/LocaleProvider.js';
|
|
@@ -315,7 +316,10 @@ const toastStackOrder = [
|
|
|
315
316
|
* Container component for rendering programmatic toasts.
|
|
316
317
|
* Place once at your app root to enable the toast API. A toast shown with a
|
|
317
318
|
* `position` appears there, and one shown without goes to the container's
|
|
318
|
-
* `position`.
|
|
319
|
+
* `position`. The toasts at one position stack in one `.toast-container`,
|
|
320
|
+
* with a gap between them, in the order they were shown, growing away from
|
|
321
|
+
* the edge of the screen. A toast shown with a `container` of its own, and
|
|
322
|
+
* not `inline`, portals there instead, in a box of its own.
|
|
319
323
|
*
|
|
320
324
|
* @function
|
|
321
325
|
* @param {{ position?: ToastPosition }} props - Container props.
|
|
@@ -326,15 +330,25 @@ const ToastContainer = ({ position = 'top-right' }) => {
|
|
|
326
330
|
// follows changes.
|
|
327
331
|
const toastList = useSyncExternalStore(toast.subscribe, getVisibleToasts, getServerToasts);
|
|
328
332
|
const resolveContainer = usePortalContainer();
|
|
333
|
+
const classPrefix = useClassPrefix();
|
|
329
334
|
if (typeof document === 'undefined' || toastList.length === 0) {
|
|
330
335
|
return null;
|
|
331
336
|
}
|
|
332
|
-
|
|
337
|
+
// A toast shown with a `container` of its own, and not `inline`, portals
|
|
338
|
+
// there in a box of its own. Every other toast renders inline in the stack
|
|
339
|
+
// for its position, so the toasts at one position stack instead of each
|
|
340
|
+
// sitting in a box of its own on top of the others. An empty `container`
|
|
341
|
+
// falls back to the page, as it does on a Toast, so it means none here.
|
|
342
|
+
const ownsContainer = (t) => !!t.props.container && !t.props.inline;
|
|
343
|
+
const renderToast = (t, at, inline) => {
|
|
344
|
+
const { queue: _queue, ...toastProps } = t.props;
|
|
345
|
+
return (jsx(Toast, { ...toastProps, position: at, inline: inline, onClose: () => toast.close(t.id) }, t.id));
|
|
346
|
+
};
|
|
347
|
+
const stacks = groupIntoPositionStacks(toastList.filter(t => !ownsContainer(t)), t => t.props.position, position, toastStackOrder);
|
|
333
348
|
const target = resolveContainer();
|
|
334
|
-
return createPortal(
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}) }, stack.key))) }), target);
|
|
349
|
+
return createPortal(jsxs(LocalePortalScope, { target: target, children: [stacks.map(stack => (jsx("div", { className: prefixedClassNames(classPrefix, 'toast-container', `is-${stack.position}`), children: stack.items.map(t => renderToast(t, stack.position, true)) }, stack.key))), toastList
|
|
350
|
+
.filter(ownsContainer)
|
|
351
|
+
.map(t => renderToast(t, t.props.position ?? position, false))] }), target);
|
|
338
352
|
};
|
|
339
353
|
|
|
340
354
|
export { Toast, ToastContainer, toast };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.js","sources":["../../../src/components/Toast.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useEffect,\n useRef,\n useState,\n useCallback,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { isEventInside } from '../helpers/shadowDom';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { usePortalContainer } from '../helpers/portal';\nimport { LocalePortalScope } from '../helpers/LocaleProvider';\nimport { groupIntoPositionStacks } from '../helpers/positionStacks';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useOverlayStack } from '../helpers/overlayStack';\n\n/** Color/style type presets for toast messages. */\nexport type ToastType =\n 'default' | 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/** Screen positions where toasts can be displayed. */\nexport type ToastPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\n/**\n * Props for the Toast component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the toast element.\n */\nexport interface ToastProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color'> {\n /** The message to display (required). */\n message: string;\n /** Color variant — colors the toast **background**. */\n type?: ToastType;\n /** Color variant — colors the **action button** text. */\n actionType?: ToastType;\n /**\n * Position on the screen. Default: 'top-right'. On a standalone `<Toast>`\n * this places it. Through `toast.show()` it places that toast, and a toast\n * shown without one goes to `ToastContainer`'s `position` instead.\n */\n position?: ToastPosition;\n /** Duration in ms before auto-close. `0` disables auto-close. */\n duration?: number;\n /** Keeps the toast visible until dismissed. */\n indefinite?: boolean;\n /** Whether clicking the toast (or outside it) dismisses it. */\n dismissible?: boolean;\n /** Show an explicit close (X) button. Default: false. */\n closable?: boolean;\n /** Pill-shaped (rounded corners). */\n rounded?: boolean;\n /** Pause auto-close timer on hover. Default: false. */\n pauseOnHover?: boolean;\n /**\n * Whether the toast can be dismissed with Escape. While a Modal, Dialog,\n * Sidebar or full-page Loading is open, Escape goes to that overlay and the\n * toast stays up, so Escape dismisses the toast once none is open. An\n * Escape a popup on the page closed on, by calling `preventDefault()`,\n * leaves it up too. Default: true.\n */\n cancelable?: boolean;\n /** Text for an action button (e.g. \"Undo\"). */\n actionText?: string;\n /** Text for a cancel button. */\n cancelText?: string;\n /** Callback when the action button is clicked. */\n onAction?: () => void;\n /** Callback when toast closes. */\n onClose?: () => void;\n /** CSS selector or DOM node to mount the toast into. */\n container?: string | HTMLElement;\n /** Renders inline instead of using a portal. */\n inline?: boolean;\n}\n\n/**\n * The `Toast` component provides brief notification messages with optional action and cancel buttons.\n *\n * @function\n * @param {ToastProps} props - Props for the Toast component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the toast element.\n * @returns {JSX.Element | null} The rendered toast component.\n *\n * @example\n * // Basic toast\n * <Toast message=\"Operation successful!\" type=\"success\" />\n *\n * @example\n * // Toast with action button\n * <Toast message=\"Item deleted\" actionText=\"Undo\" onAction={handleUndo} />\n */\nexport const Toast = forwardRef<HTMLDivElement, ToastProps>(\n (\n {\n message,\n type = 'default',\n actionType,\n position = 'top-right',\n duration = 2000,\n indefinite = false,\n dismissible = true,\n closable = false,\n rounded = false,\n pauseOnHover = false,\n cancelable = true,\n actionText,\n cancelText,\n onAction,\n onClose,\n container,\n inline = false,\n className,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const resolveContainer = usePortalContainer();\n const [isVisible, setIsVisible] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement | null>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const handleClose = useCallback(() => {\n setIsVisible(false);\n onClose?.();\n }, [onClose]);\n\n const handleAction = useCallback(() => {\n onAction?.();\n handleClose();\n }, [onAction, handleClose]);\n\n // Read when the timer runs out, a click lands outside or Escape arrives,\n // so the timer and the listeners stay put while `onClose` changes\n // identity, as an inline one does on every render of the parent. An\n // inline one from `ToastContainer` changes whenever another toast shows.\n const handleCloseRef = useLatestRef(handleClose);\n\n useEffect(() => {\n if (indefinite || duration === 0 || isPaused) return undefined;\n\n const timer = setTimeout(() => {\n handleCloseRef.current();\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, indefinite, isPaused, handleCloseRef]);\n\n const handleMouseEnter = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(true);\n }\n }, [pauseOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(false);\n }\n }, [pauseOnHover]);\n\n // Click-outside dismiss — deferred so the click that spawned the toast\n // doesn't immediately dismiss it before it's even visible.\n useEffect(() => {\n if (!dismissible || !isVisible) return undefined;\n\n const handleDocumentClick = (e: MouseEvent) => {\n if (toastRef.current && !isEventInside(e, toastRef.current)) {\n handleCloseRef.current();\n }\n };\n\n const raf = requestAnimationFrame(() => {\n document.addEventListener('click', handleDocumentClick);\n });\n\n return () => {\n cancelAnimationFrame(raf);\n document.removeEventListener('click', handleDocumentClick);\n };\n }, [dismissible, isVisible, handleCloseRef]);\n\n // A toast is a notification rather than a layer, so it never joins the\n // stack of open overlays. Asking the stack tells it whether one is open:\n // an Escape while one is belongs to the overlay, and the toast waits.\n const isTopmost = useOverlayStack(false);\n\n // On `window`, as in `Modal`, so a popup on the page has had the key\n // first, and an Escape it closed on doesn't dismiss the toast as well.\n useEffect(() => {\n if (!cancelable || !isVisible) return undefined;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !e.defaultPrevented && isTopmost()) {\n handleCloseRef.current();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [cancelable, isVisible, handleCloseRef, isTopmost]);\n\n const containerClasses = usePrefixedClassNames('toast-container', {\n [`is-${position}`]: true,\n });\n\n const toastClasses = usePrefixedClassNames('toast', {\n [`is-${type}`]: type !== 'default',\n [`is-action-${actionType}`]: !!actionType && actionType !== 'default',\n 'is-rounded': rounded,\n });\n\n const combinedClasses = classNames(\n toastClasses,\n bulmaHelperClasses,\n className\n );\n const toastMessageClass = usePrefixedClassNames('toast-message');\n const toastActionsClass = usePrefixedClassNames('toast-actions');\n const toastCancelClass = usePrefixedClassNames('toast-cancel');\n const toastActionClass = usePrefixedClassNames('toast-action');\n const toastButtonClass = usePrefixedClassNames('button');\n const toastCloseClass = usePrefixedClassNames('delete', 'is-small');\n\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n toastRef.current = node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Sidebar` and `Carousel`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split. Memoized because an\n // unstable ref identity makes React detach and re-attach on every render,\n // which would run that cleanup each time.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n if (!isVisible) {\n return null;\n }\n\n const toastElement = (\n <div\n ref={setRef}\n className={combinedClasses}\n role=\"alert\"\n aria-live={\n type === 'danger' || type === 'warning' ? 'assertive' : 'polite'\n }\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={dismissible ? handleClose : undefined}\n {...rest}\n >\n <span className={toastMessageClass}>{message}</span>\n {(cancelText || actionText) && (\n <div className={toastActionsClass}>\n {cancelText && (\n <span className={toastCancelClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n >\n {cancelText}\n </button>\n </span>\n )}\n {actionText && (\n <span className={toastActionClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleAction();\n }}\n >\n {actionText}\n </button>\n </span>\n )}\n </div>\n )}\n {closable && (\n <button\n type=\"button\"\n className={toastCloseClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n aria-label=\"Close\"\n />\n )}\n </div>\n );\n\n if (inline) {\n return toastElement;\n }\n\n const toastContent = <div className={containerClasses}>{toastElement}</div>;\n\n if (typeof document !== 'undefined') {\n const target = resolveContainer(container);\n return createPortal(\n <LocalePortalScope target={target}>{toastContent}</LocalePortalScope>,\n target\n );\n }\n\n return null;\n }\n);\n\nToast.displayName = 'Toast';\n\n// Toast Manager for programmatic toasts\n\n/**\n * Options for showing a programmatic toast. Extends ToastProps with a required message.\n */\nexport interface ToastOptions extends Omit<ToastProps, 'message'> {\n /** The message to display. */\n message: string;\n /**\n * When true, toasts enter a FIFO queue and display one at a time, one queue\n * across every `position`. Default false.\n */\n queue?: boolean;\n}\n\n/**\n * Internal representation of a toast instance.\n */\nexport interface ToastInstance {\n /** Unique identifier for this toast. */\n id: string;\n /** Configuration options for the toast. */\n props: ToastOptions;\n}\n\nlet toastId = 0;\nconst toastListeners: Set<(toasts: ToastInstance[]) => void> = new Set();\nlet toasts: ToastInstance[] = [];\n\n// Queued toasts: FIFO queue, one at a time\nlet queuedToasts: ToastInstance[] = [];\nlet currentQueuedToast: ToastInstance | null = null;\n\n// The server has nowhere to portal a toast to, and its copy of this module is\n// shared by every request, so server rendering reads an empty list. Hydration\n// reads it too, which keeps the first client render matching the server's.\nconst noToasts: ToastInstance[] = [];\nconst getServerToasts = () => noToasts;\n\n// What a container shows right now: the stacked toasts, then the queued one on\n// screen. ToastContainer renders from this rather than from updates alone, so\n// toasts raised before it mounted still appear. It is replaced rather than\n// mutated, and only when listeners are notified, because useSyncExternalStore\n// needs the same array back between changes. An empty list is `noToasts`\n// itself, so a container that hydrates with nothing to show reads the same\n// snapshot the server did and has no reason to render again.\nlet visibleToasts: ToastInstance[] = noToasts;\nconst getVisibleToasts = () => visibleToasts;\n\nconst notifyListeners = () => {\n const allVisible = [...toasts];\n if (currentQueuedToast) {\n allVisible.push(currentQueuedToast);\n }\n visibleToasts = allVisible.length > 0 ? allVisible : noToasts;\n toastListeners.forEach(listener => listener([...allVisible]));\n};\n\nconst processQueuedToast = () => {\n if (currentQueuedToast || queuedToasts.length === 0) return;\n currentQueuedToast = queuedToasts.shift()!;\n notifyListeners();\n};\n\n/**\n * Programmatic toast API for showing, closing, and managing toasts.\n *\n * @example\n * toast.success('Saved!');\n * toast.show({ message: 'Item deleted', actionText: 'Undo', onAction: handleUndo });\n */\nexport const toast = {\n /**\n * Show a toast with the given options.\n * @param {ToastOptions} options - Toast configuration.\n * @returns {string} The unique ID of the created toast.\n */\n show: (options: ToastOptions): string => {\n const id = `toast-${++toastId}`;\n const instance = { id, props: options };\n\n if (options.queue) {\n queuedToasts.push(instance);\n processQueuedToast();\n } else {\n toasts.push(instance);\n notifyListeners();\n }\n\n return id;\n },\n\n /**\n * Show a success toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n success: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'success', ...options });\n },\n\n /**\n * Show a danger toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n danger: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'danger', ...options });\n },\n\n /**\n * Show a warning toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n warning: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'warning', ...options });\n },\n\n /**\n * Show an info toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n info: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'info', ...options });\n },\n\n /**\n * Close a specific toast by ID.\n * @param {string} id - The toast ID to close.\n */\n close: (id: string): void => {\n if (currentQueuedToast && currentQueuedToast.id === id) {\n currentQueuedToast = null;\n processQueuedToast();\n } else {\n queuedToasts = queuedToasts.filter(t => t.id !== id);\n toasts = toasts.filter(t => t.id !== id);\n }\n notifyListeners();\n },\n\n /** Close all toasts and clear the queue. */\n closeAll: (): void => {\n toasts = [];\n queuedToasts = [];\n currentQueuedToast = null;\n notifyListeners();\n },\n\n /**\n * Subscribe to toast state changes.\n * @param {(toasts: ToastInstance[]) => void} listener - Callback invoked on changes.\n * @returns {() => void} Unsubscribe function.\n */\n subscribe: (listener: (toasts: ToastInstance[]) => void): (() => void) => {\n toastListeners.add(listener);\n return () => toastListeners.delete(listener);\n },\n};\n\n// The order ToastContainer renders its stacks in: across the top of the\n// screen, then across the bottom.\nconst toastStackOrder: readonly ToastPosition[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n];\n\n/**\n * Container component for rendering programmatic toasts.\n * Place once at your app root to enable the toast API. A toast shown with a\n * `position` appears there, and one shown without goes to the container's\n * `position`.\n *\n * @function\n * @param {{ position?: ToastPosition }} props - Container props.\n * @returns {JSX.Element | null} The rendered toast container, or null if empty.\n */\nexport const ToastContainer: React.FC<{\n /**\n * Where a toast shown without a `position` of its own appears. Default:\n * 'top-right'. When it changes, those toasts move without remounting, but\n * one shown with its own `position` equal to the old or new value\n * remounts and starts over as if it had just been shown.\n */\n position?: ToastPosition;\n}> = ({ position = 'top-right' }) => {\n // Starts from the toasts already showing instead of an empty list, then\n // follows changes.\n const toastList = useSyncExternalStore(\n toast.subscribe,\n getVisibleToasts,\n getServerToasts\n );\n const resolveContainer = usePortalContainer();\n\n if (typeof document === 'undefined' || toastList.length === 0) {\n return null;\n }\n\n const stacks = groupIntoPositionStacks(\n toastList,\n t => t.props.position,\n position,\n toastStackOrder\n );\n\n const target = resolveContainer();\n return createPortal(\n <LocalePortalScope target={target}>\n {stacks.map(stack => (\n <div key={stack.key} className={`toast-container is-${stack.position}`}>\n {stack.items.map(t => {\n const { queue: _queue, ...toastProps } = t.props;\n return (\n <Toast\n key={t.id}\n {...toastProps}\n position={stack.position}\n onClose={() => toast.close(t.id)}\n />\n );\n })}\n </div>\n ))}\n </LocalePortalScope>,\n target\n );\n};\n\nexport default Toast;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Toast.js","sources":["../../../src/components/Toast.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useEffect,\n useRef,\n useState,\n useCallback,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { isEventInside } from '../helpers/shadowDom';\nimport {\n classNames,\n prefixedClassNames,\n usePrefixedClassNames,\n} from '../helpers/classNames';\nimport { useClassPrefix } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { usePortalContainer } from '../helpers/portal';\nimport { LocalePortalScope } from '../helpers/LocaleProvider';\nimport { groupIntoPositionStacks } from '../helpers/positionStacks';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useOverlayStack } from '../helpers/overlayStack';\n\n/** Color/style type presets for toast messages. */\nexport type ToastType =\n 'default' | 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/** Screen positions where toasts can be displayed. */\nexport type ToastPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\n/**\n * Props for the Toast component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the toast element.\n */\nexport interface ToastProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color'> {\n /** The message to display (required). */\n message: string;\n /** Color variant — colors the toast **background**. */\n type?: ToastType;\n /** Color variant — colors the **action button** text. */\n actionType?: ToastType;\n /**\n * Position on the screen. Default: 'top-right'. On a standalone `<Toast>`\n * this places it. Through `toast.show()` it places that toast, and a toast\n * shown without one goes to `ToastContainer`'s `position` instead.\n */\n position?: ToastPosition;\n /** Duration in ms before auto-close. `0` disables auto-close. */\n duration?: number;\n /** Keeps the toast visible until dismissed. */\n indefinite?: boolean;\n /** Whether clicking the toast (or outside it) dismisses it. */\n dismissible?: boolean;\n /** Show an explicit close (X) button. Default: false. */\n closable?: boolean;\n /** Pill-shaped (rounded corners). */\n rounded?: boolean;\n /** Pause auto-close timer on hover. Default: false. */\n pauseOnHover?: boolean;\n /**\n * Whether the toast can be dismissed with Escape. While a Modal, Dialog,\n * Sidebar or full-page Loading is open, Escape goes to that overlay and the\n * toast stays up, so Escape dismisses the toast once none is open. An\n * Escape a popup on the page closed on, by calling `preventDefault()`,\n * leaves it up too. Default: true.\n */\n cancelable?: boolean;\n /** Text for an action button (e.g. \"Undo\"). */\n actionText?: string;\n /** Text for a cancel button. */\n cancelText?: string;\n /** Callback when the action button is clicked. */\n onAction?: () => void;\n /** Callback when toast closes. */\n onClose?: () => void;\n /**\n * CSS selector or DOM node to mount the toast into. Through `toast.show()`,\n * a toast with one portals there in a box of its own, rather than joining\n * `ToastContainer`'s stack for its position.\n */\n container?: string | HTMLElement;\n /**\n * Renders inline instead of using a portal. Through `toast.show()`, a toast\n * already renders inline in `ToastContainer`'s stack for its position, and\n * `inline` keeps one with a `container` in that stack too.\n */\n inline?: boolean;\n}\n\n/**\n * The `Toast` component provides brief notification messages with optional action and cancel buttons.\n *\n * @function\n * @param {ToastProps} props - Props for the Toast component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the toast element.\n * @returns {JSX.Element | null} The rendered toast component.\n *\n * @example\n * // Basic toast\n * <Toast message=\"Operation successful!\" type=\"success\" />\n *\n * @example\n * // Toast with action button\n * <Toast message=\"Item deleted\" actionText=\"Undo\" onAction={handleUndo} />\n */\nexport const Toast = forwardRef<HTMLDivElement, ToastProps>(\n (\n {\n message,\n type = 'default',\n actionType,\n position = 'top-right',\n duration = 2000,\n indefinite = false,\n dismissible = true,\n closable = false,\n rounded = false,\n pauseOnHover = false,\n cancelable = true,\n actionText,\n cancelText,\n onAction,\n onClose,\n container,\n inline = false,\n className,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const resolveContainer = usePortalContainer();\n const [isVisible, setIsVisible] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement | null>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const handleClose = useCallback(() => {\n setIsVisible(false);\n onClose?.();\n }, [onClose]);\n\n const handleAction = useCallback(() => {\n onAction?.();\n handleClose();\n }, [onAction, handleClose]);\n\n // Read when the timer runs out, a click lands outside or Escape arrives,\n // so the timer and the listeners stay put while `onClose` changes\n // identity, as an inline one does on every render of the parent. An\n // inline one from `ToastContainer` changes whenever another toast shows.\n const handleCloseRef = useLatestRef(handleClose);\n\n useEffect(() => {\n if (indefinite || duration === 0 || isPaused) return undefined;\n\n const timer = setTimeout(() => {\n handleCloseRef.current();\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, indefinite, isPaused, handleCloseRef]);\n\n const handleMouseEnter = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(true);\n }\n }, [pauseOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(false);\n }\n }, [pauseOnHover]);\n\n // Click-outside dismiss — deferred so the click that spawned the toast\n // doesn't immediately dismiss it before it's even visible.\n useEffect(() => {\n if (!dismissible || !isVisible) return undefined;\n\n const handleDocumentClick = (e: MouseEvent) => {\n if (toastRef.current && !isEventInside(e, toastRef.current)) {\n handleCloseRef.current();\n }\n };\n\n const raf = requestAnimationFrame(() => {\n document.addEventListener('click', handleDocumentClick);\n });\n\n return () => {\n cancelAnimationFrame(raf);\n document.removeEventListener('click', handleDocumentClick);\n };\n }, [dismissible, isVisible, handleCloseRef]);\n\n // A toast is a notification rather than a layer, so it never joins the\n // stack of open overlays. Asking the stack tells it whether one is open:\n // an Escape while one is belongs to the overlay, and the toast waits.\n const isTopmost = useOverlayStack(false);\n\n // On `window`, as in `Modal`, so a popup on the page has had the key\n // first, and an Escape it closed on doesn't dismiss the toast as well.\n useEffect(() => {\n if (!cancelable || !isVisible) return undefined;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !e.defaultPrevented && isTopmost()) {\n handleCloseRef.current();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [cancelable, isVisible, handleCloseRef, isTopmost]);\n\n const containerClasses = usePrefixedClassNames('toast-container', {\n [`is-${position}`]: true,\n });\n\n const toastClasses = usePrefixedClassNames('toast', {\n [`is-${type}`]: type !== 'default',\n [`is-action-${actionType}`]: !!actionType && actionType !== 'default',\n 'is-rounded': rounded,\n });\n\n const combinedClasses = classNames(\n toastClasses,\n bulmaHelperClasses,\n className\n );\n const toastMessageClass = usePrefixedClassNames('toast-message');\n const toastActionsClass = usePrefixedClassNames('toast-actions');\n const toastCancelClass = usePrefixedClassNames('toast-cancel');\n const toastActionClass = usePrefixedClassNames('toast-action');\n const toastButtonClass = usePrefixedClassNames('button');\n const toastCloseClass = usePrefixedClassNames('delete', 'is-small');\n\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n toastRef.current = node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Sidebar` and `Carousel`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split. Memoized because an\n // unstable ref identity makes React detach and re-attach on every render,\n // which would run that cleanup each time.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n if (!isVisible) {\n return null;\n }\n\n const toastElement = (\n <div\n ref={setRef}\n className={combinedClasses}\n role=\"alert\"\n aria-live={\n type === 'danger' || type === 'warning' ? 'assertive' : 'polite'\n }\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={dismissible ? handleClose : undefined}\n {...rest}\n >\n <span className={toastMessageClass}>{message}</span>\n {(cancelText || actionText) && (\n <div className={toastActionsClass}>\n {cancelText && (\n <span className={toastCancelClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n >\n {cancelText}\n </button>\n </span>\n )}\n {actionText && (\n <span className={toastActionClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleAction();\n }}\n >\n {actionText}\n </button>\n </span>\n )}\n </div>\n )}\n {closable && (\n <button\n type=\"button\"\n className={toastCloseClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n aria-label=\"Close\"\n />\n )}\n </div>\n );\n\n if (inline) {\n return toastElement;\n }\n\n const toastContent = <div className={containerClasses}>{toastElement}</div>;\n\n if (typeof document !== 'undefined') {\n const target = resolveContainer(container);\n return createPortal(\n <LocalePortalScope target={target}>{toastContent}</LocalePortalScope>,\n target\n );\n }\n\n return null;\n }\n);\n\nToast.displayName = 'Toast';\n\n// Toast Manager for programmatic toasts\n\n/**\n * Options for showing a programmatic toast. Extends ToastProps with a required message.\n */\nexport interface ToastOptions extends Omit<ToastProps, 'message'> {\n /** The message to display. */\n message: string;\n /**\n * When true, toasts enter a FIFO queue and display one at a time, one queue\n * across every `position`. Default false.\n */\n queue?: boolean;\n}\n\n/**\n * Internal representation of a toast instance.\n */\nexport interface ToastInstance {\n /** Unique identifier for this toast. */\n id: string;\n /** Configuration options for the toast. */\n props: ToastOptions;\n}\n\nlet toastId = 0;\nconst toastListeners: Set<(toasts: ToastInstance[]) => void> = new Set();\nlet toasts: ToastInstance[] = [];\n\n// Queued toasts: FIFO queue, one at a time\nlet queuedToasts: ToastInstance[] = [];\nlet currentQueuedToast: ToastInstance | null = null;\n\n// The server has nowhere to portal a toast to, and its copy of this module is\n// shared by every request, so server rendering reads an empty list. Hydration\n// reads it too, which keeps the first client render matching the server's.\nconst noToasts: ToastInstance[] = [];\nconst getServerToasts = () => noToasts;\n\n// What a container shows right now: the stacked toasts, then the queued one on\n// screen. ToastContainer renders from this rather than from updates alone, so\n// toasts raised before it mounted still appear. It is replaced rather than\n// mutated, and only when listeners are notified, because useSyncExternalStore\n// needs the same array back between changes. An empty list is `noToasts`\n// itself, so a container that hydrates with nothing to show reads the same\n// snapshot the server did and has no reason to render again.\nlet visibleToasts: ToastInstance[] = noToasts;\nconst getVisibleToasts = () => visibleToasts;\n\nconst notifyListeners = () => {\n const allVisible = [...toasts];\n if (currentQueuedToast) {\n allVisible.push(currentQueuedToast);\n }\n visibleToasts = allVisible.length > 0 ? allVisible : noToasts;\n toastListeners.forEach(listener => listener([...allVisible]));\n};\n\nconst processQueuedToast = () => {\n if (currentQueuedToast || queuedToasts.length === 0) return;\n currentQueuedToast = queuedToasts.shift()!;\n notifyListeners();\n};\n\n/**\n * Programmatic toast API for showing, closing, and managing toasts.\n *\n * @example\n * toast.success('Saved!');\n * toast.show({ message: 'Item deleted', actionText: 'Undo', onAction: handleUndo });\n */\nexport const toast = {\n /**\n * Show a toast with the given options.\n * @param {ToastOptions} options - Toast configuration.\n * @returns {string} The unique ID of the created toast.\n */\n show: (options: ToastOptions): string => {\n const id = `toast-${++toastId}`;\n const instance = { id, props: options };\n\n if (options.queue) {\n queuedToasts.push(instance);\n processQueuedToast();\n } else {\n toasts.push(instance);\n notifyListeners();\n }\n\n return id;\n },\n\n /**\n * Show a success toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n success: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'success', ...options });\n },\n\n /**\n * Show a danger toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n danger: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'danger', ...options });\n },\n\n /**\n * Show a warning toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n warning: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'warning', ...options });\n },\n\n /**\n * Show an info toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n info: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'info', ...options });\n },\n\n /**\n * Close a specific toast by ID.\n * @param {string} id - The toast ID to close.\n */\n close: (id: string): void => {\n if (currentQueuedToast && currentQueuedToast.id === id) {\n currentQueuedToast = null;\n processQueuedToast();\n } else {\n queuedToasts = queuedToasts.filter(t => t.id !== id);\n toasts = toasts.filter(t => t.id !== id);\n }\n notifyListeners();\n },\n\n /** Close all toasts and clear the queue. */\n closeAll: (): void => {\n toasts = [];\n queuedToasts = [];\n currentQueuedToast = null;\n notifyListeners();\n },\n\n /**\n * Subscribe to toast state changes.\n * @param {(toasts: ToastInstance[]) => void} listener - Callback invoked on changes.\n * @returns {() => void} Unsubscribe function.\n */\n subscribe: (listener: (toasts: ToastInstance[]) => void): (() => void) => {\n toastListeners.add(listener);\n return () => toastListeners.delete(listener);\n },\n};\n\n// The order ToastContainer renders its stacks in: across the top of the\n// screen, then across the bottom.\nconst toastStackOrder: readonly ToastPosition[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n];\n\n/**\n * Container component for rendering programmatic toasts.\n * Place once at your app root to enable the toast API. A toast shown with a\n * `position` appears there, and one shown without goes to the container's\n * `position`. The toasts at one position stack in one `.toast-container`,\n * with a gap between them, in the order they were shown, growing away from\n * the edge of the screen. A toast shown with a `container` of its own, and\n * not `inline`, portals there instead, in a box of its own.\n *\n * @function\n * @param {{ position?: ToastPosition }} props - Container props.\n * @returns {JSX.Element | null} The rendered toast container, or null if empty.\n */\nexport const ToastContainer: React.FC<{\n /**\n * Where a toast shown without a `position` of its own appears. Default:\n * 'top-right'. When it changes, those toasts move without remounting, but\n * one shown with its own `position` equal to the old or new value\n * remounts and starts over as if it had just been shown.\n */\n position?: ToastPosition;\n}> = ({ position = 'top-right' }) => {\n // Starts from the toasts already showing instead of an empty list, then\n // follows changes.\n const toastList = useSyncExternalStore(\n toast.subscribe,\n getVisibleToasts,\n getServerToasts\n );\n const resolveContainer = usePortalContainer();\n const classPrefix = useClassPrefix();\n\n if (typeof document === 'undefined' || toastList.length === 0) {\n return null;\n }\n\n // A toast shown with a `container` of its own, and not `inline`, portals\n // there in a box of its own. Every other toast renders inline in the stack\n // for its position, so the toasts at one position stack instead of each\n // sitting in a box of its own on top of the others. An empty `container`\n // falls back to the page, as it does on a Toast, so it means none here.\n const ownsContainer = (t: ToastInstance) =>\n !!t.props.container && !t.props.inline;\n const renderToast = (\n t: ToastInstance,\n at: ToastPosition,\n inline: boolean\n ) => {\n const { queue: _queue, ...toastProps } = t.props;\n return (\n <Toast\n key={t.id}\n {...toastProps}\n position={at}\n inline={inline}\n onClose={() => toast.close(t.id)}\n />\n );\n };\n\n const stacks = groupIntoPositionStacks(\n toastList.filter(t => !ownsContainer(t)),\n t => t.props.position,\n position,\n toastStackOrder\n );\n\n const target = resolveContainer();\n return createPortal(\n <LocalePortalScope target={target}>\n {stacks.map(stack => (\n <div\n key={stack.key}\n className={prefixedClassNames(\n classPrefix,\n 'toast-container',\n `is-${stack.position}`\n )}\n >\n {stack.items.map(t => renderToast(t, stack.position, true))}\n </div>\n ))}\n {toastList\n .filter(ownsContainer)\n .map(t => renderToast(t, t.props.position ?? position, false))}\n </LocalePortalScope>,\n target\n );\n};\n\nexport default Toast;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tr.js","sources":["../../../src/elements/Tr.tsx"],"sourcesContent":["/**\n * @group Table\n */\nimport React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { TableColor, validTableColors } from './Td'; // Import TableColor from Td\n\n/**\n * Props for the Tr component.\n */\nexport interface TrProps\n extends\n Omit<React.HTMLAttributes<HTMLTableRowElement>, 'color'>,\n Omit<BulmaClassesProps, 'backgroundColor' | 'color'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * Whether the row is selected (adds Bulma's is-selected class). It's a look\n * only: it says nothing to assistive tech, so pair it with a checkbox named\n * for the row when the selection matters. A bestax `Checkbox`
|
|
1
|
+
{"version":3,"file":"Tr.js","sources":["../../../src/elements/Tr.tsx"],"sourcesContent":["/**\n * @group Table\n */\nimport React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { TableColor, validTableColors } from './Td'; // Import TableColor from Td\n\n/**\n * Props for the Tr component.\n */\nexport interface TrProps\n extends\n Omit<React.HTMLAttributes<HTMLTableRowElement>, 'color'>,\n Omit<BulmaClassesProps, 'backgroundColor' | 'color'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * Whether the row is selected (adds Bulma's is-selected class). It's a look\n * only: it says nothing to assistive tech, so pair it with a checkbox named\n * for the row when the selection matters. A bestax `Checkbox` or `Radio`\n * placed straight in one of the row's cells takes the row's text color, so\n * a checked one shows on the row's fill. One in a menu or a table nested in a\n * cell, or in a cell with a `color` of its own, keeps its own colors, since\n * it sits on that surface instead, and so does every one in a row with a\n * `color`, whose cells paint that color over the fill.\n */\n isSelected?: boolean;\n /** Bulma color modifier for the table row. */\n color?: TableColor;\n /** Table row content (cells). */\n children?: React.ReactNode;\n}\n\n/**\n * Tr component for rendering a styled Bulma table row.\n *\n * Supports the is-selected modifier and color modifiers.\n *\n * @function\n * @param {TrProps} props - Props for the Tr component.\n * @returns {JSX.Element} The rendered table row element.\n * @see {@link https://bulma.io/documentation/elements/table/#table-row | Bulma Table documentation}\n */\nexport const Tr: React.FC<TrProps> = ({\n className,\n isSelected,\n color,\n children,\n ...props\n}) => {\n const bulmaClasses = usePrefixedClassNames('', {\n 'is-selected': isSelected,\n [`is-${color}`]: color && validTableColors.includes(color),\n });\n\n /**\n * Generates Bulma helper classes and separates out remaining props.\n */\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n const trClasses = classNames(bulmaClasses, className, bulmaHelperClasses);\n\n return (\n <tr className={trClasses || undefined} {...rest}>\n {children}\n </tr>\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;;;AAkCA;;;;;;;;;AASG;AACI,MAAM,EAAE,GAAsB,CAAC,EACpC,SAAS,EACT,UAAU,EACV,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,YAAY,GAAG,qBAAqB,CAAC,EAAE,EAAE;AAC7C,QAAA,aAAa,EAAE,UAAU;AACzB,QAAA,CAAC,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,GAAG,KAAK,IAAI,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC3D,KAAA,CAAC;AAEF;;AAEG;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;IAElE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,SAAS,EAAE,kBAAkB,CAAC;AAEzE,IAAA,QACEA,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAE,SAAS,IAAI,SAAS,EAAA,GAAM,IAAI,EAAA,QAAA,EAC5C,QAAQ,EAAA,CACN;AAET;;"}
|
|
@@ -5,7 +5,7 @@ import { forwardRef, useRef, useCallback } from 'react';
|
|
|
5
5
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
6
6
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
7
7
|
import { useClientLayoutEffect } from '../helpers/useClientLayoutEffect.js';
|
|
8
|
-
import { useFieldsetDisabled, useCheckboxesGroup } from './FormContext.js';
|
|
8
|
+
import { useFieldsetDisabled, useCheckboxesGroup, useRegisterChecked } from './FormContext.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* The values the Checkbox `color` prop accepts, as a readonly tuple.
|
|
@@ -102,15 +102,22 @@ const Checkbox = forwardRef(({ color, size, className, children, textColor, disa
|
|
|
102
102
|
// Local props always win over the group (explicit > implicit).
|
|
103
103
|
const group = useCheckboxesGroup();
|
|
104
104
|
const effectiveName = name ?? group?.name;
|
|
105
|
-
// Group-managed checked state — only when the group
|
|
106
|
-
//
|
|
107
|
-
// has a value to compare against. Local `checked` always wins.
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
// Group-managed checked state — only when the group manages the selection
|
|
106
|
+
// (it was given `value`, `defaultValue` or `onChange`) AND this Checkbox
|
|
107
|
+
// has a value to compare against. Local `checked` always wins. A group
|
|
108
|
+
// given only `onChange` holds no value until its first change, and until
|
|
109
|
+
// then the box shows its own `defaultChecked`, controlled all the same,
|
|
110
|
+
// so that change doesn't flip it from uncontrolled to controlled.
|
|
111
|
+
const valueKey = value === undefined ? undefined : String(value);
|
|
112
|
+
const groupManaged = group?.onChange !== undefined && valueKey !== undefined;
|
|
113
|
+
const groupHas = groupManaged &&
|
|
114
|
+
(group.value ? group.value.includes(valueKey) : !!defaultChecked);
|
|
110
115
|
const effectiveChecked = checked !== undefined ? checked : groupManaged ? groupHas : undefined;
|
|
111
116
|
// When the group manages checked, suppress local defaultChecked to avoid
|
|
112
117
|
// the controlled/uncontrolled React warning.
|
|
113
118
|
const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;
|
|
119
|
+
// What the box starts as, so the group's first change starts from it.
|
|
120
|
+
useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));
|
|
114
121
|
const handleChange = useCallback((e) => {
|
|
115
122
|
// The click that got here cleared the mixed state. Put it back now,
|
|
116
123
|
// since a click that changes no state renders nothing to do it.
|
|
@@ -119,18 +126,18 @@ const Checkbox = forwardRef(({ color, size, className, children, textColor, disa
|
|
|
119
126
|
// Local onChange always fires.
|
|
120
127
|
onChange?.(e);
|
|
121
128
|
// Dispatch to the group additionally — toggle this value's
|
|
122
|
-
// membership in the group's array
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const currentArr = group.value ??
|
|
129
|
+
// membership in the group's array, or in what was checked when the
|
|
130
|
+
// group holds no value yet.
|
|
131
|
+
if (group?.onChange && valueKey !== undefined) {
|
|
132
|
+
const currentArr = group.value ?? group.startingValue();
|
|
126
133
|
const next = e.target.checked
|
|
127
|
-
? currentArr.includes(
|
|
134
|
+
? currentArr.includes(valueKey)
|
|
128
135
|
? currentArr
|
|
129
|
-
: [...currentArr,
|
|
130
|
-
: currentArr.filter(v => v !==
|
|
136
|
+
: [...currentArr, valueKey]
|
|
137
|
+
: currentArr.filter(v => v !== valueKey);
|
|
131
138
|
group.onChange(next);
|
|
132
139
|
}
|
|
133
|
-
}, [onChange, group,
|
|
140
|
+
}, [onChange, group, valueKey, indeterminate]);
|
|
134
141
|
const mainClass = usePrefixedClassNames('styled-checkbox', 'checkbox', {
|
|
135
142
|
[`is-${color}`]: color && checkboxColors.includes(color),
|
|
136
143
|
[`is-${size}`]: size && checkboxSizes.includes(size),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.js","sources":["../../../src/form/Checkbox.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport { useCheckboxesGroup, useFieldsetDisabled } from './FormContext';\n\n/**\n * The values the Checkbox `color` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['color']` is typed from it, so the two list the same values.\n * Map over it to build a color picker, or check a value that arrives at\n * runtime before passing it in: the component adds no color class for a value\n * outside the tuple.\n *\n * @example\n * import { Checkbox, checkboxColors } from '@allxsmith/bestax-bulma';\n *\n * checkboxColors.map(color => (\n * <Checkbox key={color} color={color}>\n * {color}\n * </Checkbox>\n * ));\n */\nexport const checkboxColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n\n/**\n * The values the Checkbox `size` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['size']` is typed from it, so the two list the same values.\n * Use it to offer a size choice or to check a value that arrives at runtime:\n * the component adds no size class for a value outside the tuple. These are\n * element sizes, not the spacing scale in `validSizes`.\n *\n * @example\n * import { checkboxSizes } from '@allxsmith/bestax-bulma';\n *\n * type CheckboxSize = (typeof checkboxSizes)[number];\n */\nexport const checkboxSizes = ['small', 'normal', 'medium', 'large'] as const;\n\n/**\n * Props for the Checkbox component.\n *\n * @helperProps Helper props go on the outer `<label>`, with `className`. The\n * other attributes go on the `<input>`.\n */\nexport interface CheckboxProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'color'\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /** Color of the checkbox. */\n color?: (typeof checkboxColors)[number];\n /** Size of the checkbox. */\n size?: (typeof checkboxSizes)[number];\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Whether the checkbox is disabled. */\n disabled?: boolean;\n /**\n * Shows the mixed state, as in a \"Select all\" box when some of what it\n * covers is checked. It's a look and an announcement only: `checked` is\n * still the value, and a click still toggles `checked`. Set to `true` or\n * `false`, it's controlled: a browser clears the mixed state on a click,\n * so the component sets it again from this prop after every click and\n * every render. Unset isn't `false`. The component leaves the input's own\n * `indeterminate` property alone, so a ref can set it, and going from set\n * to unset clears it once and hands it back. It has no HTML attribute, so\n * server-rendered markup can't carry it, and a mixed box renders unmixed\n * until hydration.\n */\n indeterminate?: boolean;\n /**\n * Additional CSS classes, on the outer `<label>`. That's the element that\n * declares the `--bulma-checkbox-*` variables, so a class is how to set\n * one: `style` and the other input attributes go to the `<input>`. Name\n * `.styled-checkbox` beside your class in the selector, so it beats the\n * label's own declaration whatever order the stylesheets load in. A\n * `color` prop declares the fills again on `.styled-checkbox.is-<color>`,\n * which ties that selector, so leave `color` unset when a class sets them.\n */\n className?: string;\n /** The label/content for the checkbox. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Checkbox` component provides a Bulma-styled checkbox input.\n *\n * @function\n * @param {CheckboxProps} props - Props for the Checkbox component.\n * @returns {JSX.Element} The rendered checkbox element.\n *\n * @example\n * // Basic checkbox\n * <Checkbox>Accept terms</Checkbox>\n *\n * @example\n * // Inside a group\n * <Checkboxes name=\"tags\" defaultValue={['react']}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * </Checkboxes>\n */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n (\n {\n color,\n size,\n className,\n children,\n textColor,\n disabled: disabledProp,\n name,\n value,\n checked,\n defaultChecked,\n indeterminate,\n onChange,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n ...props,\n });\n\n // The input's own ref, merged with the forwarded one. A callback ref's\n // return value is handed back, so React 19 still runs a cleanup it\n // returns, as it did when the ref went straight to the input.\n const inputRef = useRef<HTMLInputElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') return ref(node);\n if (ref) ref.current = node;\n },\n [ref]\n );\n\n // `indeterminate` is a DOM property with no attribute, so it's set on the\n // input rather than rendered. A click clears it, so this runs after every\n // render, not only when the prop changes. Unset, it's left alone, so a\n // ref that sets the property itself still works. `ownsIndeterminateRef`\n // remembers that this component set it, so a prop that goes back to unset\n // clears the dash once instead of leaving it on.\n const ownsIndeterminateRef = useRef(false);\n useClientLayoutEffect(() => {\n if (indeterminate !== undefined) {\n ownsIndeterminateRef.current = true;\n inputRef.current!.indeterminate = indeterminate;\n } else if (ownsIndeterminateRef.current) {\n ownsIndeterminateRef.current = false;\n inputRef.current!.indeterminate = false;\n }\n });\n\n // Inherit name + selection state from a surrounding <Checkboxes> group.\n // Local props always win over the group (explicit > implicit).\n const group = useCheckboxesGroup();\n const effectiveName = name ?? group?.name;\n\n // Group-managed checked state — only when the group is in\n // controlled/uncontrolled mode (group.value is defined) AND this Checkbox\n // has a value to compare against. Local `checked` always wins.\n const groupManaged = group?.value !== undefined && value !== undefined;\n const groupHas = groupManaged && group!.value!.includes(String(value));\n const effectiveChecked =\n checked !== undefined ? checked : groupManaged ? groupHas : undefined;\n // When the group manages checked, suppress local defaultChecked to avoid\n // the controlled/uncontrolled React warning.\n const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // The click that got here cleared the mixed state. Put it back now,\n // since a click that changes no state renders nothing to do it.\n if (indeterminate !== undefined) e.target.indeterminate = indeterminate;\n // Local onChange always fires.\n onChange?.(e);\n // Dispatch to the group additionally — toggle this value's\n // membership in the group's array.\n if (group?.onChange && value !== undefined) {\n const valStr = String(value);\n const currentArr = group.value ?? [];\n const next = e.target.checked\n ? currentArr.includes(valStr)\n ? currentArr\n : [...currentArr, valStr]\n : currentArr.filter(v => v !== valStr);\n group.onChange(next);\n }\n },\n [onChange, group, value, indeterminate]\n );\n\n const mainClass = usePrefixedClassNames('styled-checkbox', 'checkbox', {\n [`is-${color}`]: color && checkboxColors.includes(color),\n [`is-${size}`]: size && checkboxSizes.includes(size),\n });\n const checkboxClass = classNames(mainClass, bulmaHelperClasses, className);\n const checkClass = usePrefixedClassNames('check');\n const controlLabelClass = usePrefixedClassNames('control-label');\n\n return (\n <label className={checkboxClass}>\n <input\n ref={setRefs}\n type=\"checkbox\"\n disabled={disabled}\n name={effectiveName}\n value={value}\n checked={effectiveChecked}\n defaultChecked={effectiveDefaultChecked}\n onChange={handleChange}\n {...rest}\n />\n <span className={checkClass} />\n {children && <span className={controlLabelClass}>{children}</span>}\n </label>\n );\n }\n);\n\nCheckbox.displayName = 'Checkbox';\n\nexport default Checkbox;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Checkbox.js","sources":["../../../src/form/Checkbox.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport {\n useCheckboxesGroup,\n useFieldsetDisabled,\n useRegisterChecked,\n} from './FormContext';\n\n/**\n * The values the Checkbox `color` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['color']` is typed from it, so the two list the same values.\n * Map over it to build a color picker, or check a value that arrives at\n * runtime before passing it in: the component adds no color class for a value\n * outside the tuple.\n *\n * @example\n * import { Checkbox, checkboxColors } from '@allxsmith/bestax-bulma';\n *\n * checkboxColors.map(color => (\n * <Checkbox key={color} color={color}>\n * {color}\n * </Checkbox>\n * ));\n */\nexport const checkboxColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n\n/**\n * The values the Checkbox `size` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['size']` is typed from it, so the two list the same values.\n * Use it to offer a size choice or to check a value that arrives at runtime:\n * the component adds no size class for a value outside the tuple. These are\n * element sizes, not the spacing scale in `validSizes`.\n *\n * @example\n * import { checkboxSizes } from '@allxsmith/bestax-bulma';\n *\n * type CheckboxSize = (typeof checkboxSizes)[number];\n */\nexport const checkboxSizes = ['small', 'normal', 'medium', 'large'] as const;\n\n/**\n * Props for the Checkbox component.\n *\n * @helperProps Helper props go on the outer `<label>`, with `className`. The\n * other attributes go on the `<input>`.\n */\nexport interface CheckboxProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'color'\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /** Color of the checkbox. */\n color?: (typeof checkboxColors)[number];\n /** Size of the checkbox. */\n size?: (typeof checkboxSizes)[number];\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Whether the checkbox is disabled. */\n disabled?: boolean;\n /**\n * Shows the mixed state, as in a \"Select all\" box when some of what it\n * covers is checked. It's a look and an announcement only: `checked` is\n * still the value, and a click still toggles `checked`. Set to `true` or\n * `false`, it's controlled: a browser clears the mixed state on a click,\n * so the component sets it again from this prop after every click and\n * every render. Unset isn't `false`. The component leaves the input's own\n * `indeterminate` property alone, so a ref can set it, and going from set\n * to unset clears it once and hands it back. It has no HTML attribute, so\n * server-rendered markup can't carry it, and a mixed box renders unmixed\n * until hydration.\n */\n indeterminate?: boolean;\n /**\n * Additional CSS classes, on the outer `<label>`. That's the element that\n * declares the `--bulma-checkbox-*` variables, so a class is how to set\n * one: `style` and the other input attributes go to the `<input>`. Name\n * `.styled-checkbox` beside your class in the selector, so it beats the\n * label's own declaration whatever order the stylesheets load in. A\n * `color` prop declares the fills again on `.styled-checkbox.is-<color>`,\n * which ties that selector, so leave `color` unset when a class sets them.\n */\n className?: string;\n /** The label/content for the checkbox. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Checkbox` component provides a Bulma-styled checkbox input.\n *\n * @function\n * @param {CheckboxProps} props - Props for the Checkbox component.\n * @returns {JSX.Element} The rendered checkbox element.\n *\n * @example\n * // Basic checkbox\n * <Checkbox>Accept terms</Checkbox>\n *\n * @example\n * // Inside a group\n * <Checkboxes name=\"tags\" defaultValue={['react']}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * </Checkboxes>\n */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n (\n {\n color,\n size,\n className,\n children,\n textColor,\n disabled: disabledProp,\n name,\n value,\n checked,\n defaultChecked,\n indeterminate,\n onChange,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n ...props,\n });\n\n // The input's own ref, merged with the forwarded one. A callback ref's\n // return value is handed back, so React 19 still runs a cleanup it\n // returns, as it did when the ref went straight to the input.\n const inputRef = useRef<HTMLInputElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') return ref(node);\n if (ref) ref.current = node;\n },\n [ref]\n );\n\n // `indeterminate` is a DOM property with no attribute, so it's set on the\n // input rather than rendered. A click clears it, so this runs after every\n // render, not only when the prop changes. Unset, it's left alone, so a\n // ref that sets the property itself still works. `ownsIndeterminateRef`\n // remembers that this component set it, so a prop that goes back to unset\n // clears the dash once instead of leaving it on.\n const ownsIndeterminateRef = useRef(false);\n useClientLayoutEffect(() => {\n if (indeterminate !== undefined) {\n ownsIndeterminateRef.current = true;\n inputRef.current!.indeterminate = indeterminate;\n } else if (ownsIndeterminateRef.current) {\n ownsIndeterminateRef.current = false;\n inputRef.current!.indeterminate = false;\n }\n });\n\n // Inherit name + selection state from a surrounding <Checkboxes> group.\n // Local props always win over the group (explicit > implicit).\n const group = useCheckboxesGroup();\n const effectiveName = name ?? group?.name;\n\n // Group-managed checked state — only when the group manages the selection\n // (it was given `value`, `defaultValue` or `onChange`) AND this Checkbox\n // has a value to compare against. Local `checked` always wins. A group\n // given only `onChange` holds no value until its first change, and until\n // then the box shows its own `defaultChecked`, controlled all the same,\n // so that change doesn't flip it from uncontrolled to controlled.\n const valueKey = value === undefined ? undefined : String(value);\n const groupManaged =\n group?.onChange !== undefined && valueKey !== undefined;\n const groupHas =\n groupManaged &&\n (group!.value ? group!.value.includes(valueKey!) : !!defaultChecked);\n const effectiveChecked =\n checked !== undefined ? checked : groupManaged ? groupHas : undefined;\n // When the group manages checked, suppress local defaultChecked to avoid\n // the controlled/uncontrolled React warning.\n const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;\n // What the box starts as, so the group's first change starts from it.\n useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // The click that got here cleared the mixed state. Put it back now,\n // since a click that changes no state renders nothing to do it.\n if (indeterminate !== undefined) e.target.indeterminate = indeterminate;\n // Local onChange always fires.\n onChange?.(e);\n // Dispatch to the group additionally — toggle this value's\n // membership in the group's array, or in what was checked when the\n // group holds no value yet.\n if (group?.onChange && valueKey !== undefined) {\n const currentArr = group.value ?? group.startingValue!();\n const next = e.target.checked\n ? currentArr.includes(valueKey)\n ? currentArr\n : [...currentArr, valueKey]\n : currentArr.filter(v => v !== valueKey);\n group.onChange(next);\n }\n },\n [onChange, group, valueKey, indeterminate]\n );\n\n const mainClass = usePrefixedClassNames('styled-checkbox', 'checkbox', {\n [`is-${color}`]: color && checkboxColors.includes(color),\n [`is-${size}`]: size && checkboxSizes.includes(size),\n });\n const checkboxClass = classNames(mainClass, bulmaHelperClasses, className);\n const checkClass = usePrefixedClassNames('check');\n const controlLabelClass = usePrefixedClassNames('control-label');\n\n return (\n <label className={checkboxClass}>\n <input\n ref={setRefs}\n type=\"checkbox\"\n disabled={disabled}\n name={effectiveName}\n value={value}\n checked={effectiveChecked}\n defaultChecked={effectiveDefaultChecked}\n onChange={handleChange}\n {...rest}\n />\n <span className={checkClass} />\n {children && <span className={controlLabelClass}>{children}</span>}\n </label>\n );\n }\n);\n\nCheckbox.displayName = 'Checkbox';\n\nexport default Checkbox;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { forwardRef, useRef, useCallback, useId } from 'react';
|
|
|
5
5
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
6
6
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
7
7
|
import { useClientLayoutEffect } from '../helpers/useClientLayoutEffect.js';
|
|
8
|
-
import { useFieldsetDisabled, useCheckboxesGroup } from './FormContext.js';
|
|
8
|
+
import { useFieldsetDisabled, useCheckboxesGroup, useRegisterChecked } from './FormContext.js';
|
|
9
9
|
|
|
10
10
|
// The colors `Checkbox` takes, as `checkboxColors` lists them. Declared here as
|
|
11
11
|
// well, so the API page can read them off this module, and a type test holds
|
|
@@ -69,30 +69,36 @@ const CheckboxCard = forwardRef(({ title, description, children, hasIndicator =
|
|
|
69
69
|
});
|
|
70
70
|
// A surrounding <Checkboxes> hands down its name and, when it manages
|
|
71
71
|
// the selection, whether this card's value is in it. The card's own
|
|
72
|
-
// props win, as they do on Checkbox.
|
|
72
|
+
// props win, as they do on Checkbox. A group given only `onChange` holds
|
|
73
|
+
// no value until its first change, and until then the card shows its own
|
|
74
|
+
// `defaultChecked`, controlled all the same, and registers it, so that
|
|
75
|
+
// change starts from what was checked, as Checkbox does.
|
|
73
76
|
const group = useCheckboxesGroup();
|
|
74
77
|
const effectiveName = name ?? group?.name;
|
|
75
|
-
const
|
|
78
|
+
const valueKey = value === undefined ? undefined : String(value);
|
|
79
|
+
const groupManaged = group?.onChange !== undefined && valueKey !== undefined;
|
|
76
80
|
const effectiveChecked = checked !== undefined
|
|
77
81
|
? checked
|
|
78
82
|
: groupManaged
|
|
79
|
-
? group.value
|
|
83
|
+
? group.value
|
|
84
|
+
? group.value.includes(valueKey)
|
|
85
|
+
: !!defaultChecked
|
|
80
86
|
: undefined;
|
|
81
87
|
const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;
|
|
88
|
+
useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));
|
|
82
89
|
const handleChange = useCallback((e) => {
|
|
83
90
|
if (indeterminate !== undefined)
|
|
84
91
|
e.target.indeterminate = indeterminate;
|
|
85
92
|
onChange?.(e);
|
|
86
|
-
if (group?.onChange &&
|
|
87
|
-
const
|
|
88
|
-
const current = group.value ?? [];
|
|
93
|
+
if (group?.onChange && valueKey !== undefined) {
|
|
94
|
+
const current = group.value ?? group.startingValue();
|
|
89
95
|
group.onChange(e.target.checked
|
|
90
|
-
? current.includes(
|
|
96
|
+
? current.includes(valueKey)
|
|
91
97
|
? current
|
|
92
|
-
: [...current,
|
|
93
|
-
: current.filter(v => v !==
|
|
98
|
+
: [...current, valueKey]
|
|
99
|
+
: current.filter(v => v !== valueKey));
|
|
94
100
|
}
|
|
95
|
-
}, [onChange, group,
|
|
101
|
+
}, [onChange, group, valueKey, indeterminate]);
|
|
96
102
|
// The title names the input and the description describes it. A name
|
|
97
103
|
// passed in wins, and without one of either the label's own text names
|
|
98
104
|
// the input, description included, so it isn't described again.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckboxCard.js","sources":["../../../src/form/CheckboxCard.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useId, useRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport { useCheckboxesGroup, useFieldsetDisabled } from './FormContext';\n\n// The colors `Checkbox` takes, as `checkboxColors` lists them. Declared here as\n// well, so the API page can read them off this module, and a type test holds\n// the two lists to each other.\nconst checkboxCardColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n\n/**\n * Props for the CheckboxCard component.\n *\n * @helperProps Helper props go on the outer `<label>`, the `.card`, with\n * `className`. The other attributes go on the `<input>`.\n * @extraProp {string} [name] - The form field name. Inside `Checkboxes`, the group's `name` when this is unset.\n * @extraProp {string} [value] - What a form sends for the card when it's checked. Inside a `Checkboxes` group that takes `value`, `defaultValue` or `onChange`, the card is checked while the group's value holds it.\n */\nexport interface CheckboxCardProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'color' | 'title'\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /**\n * What the option is, such as \"Daily backups\". It names the checkbox, so\n * a screen reader says it with the state. Without it, the card's whole\n * text names the checkbox, as a label's text does.\n */\n title?: React.ReactNode;\n /**\n * A line or two about the option, read after the name and the state. It's\n * the checkbox's description when `title`, `aria-label` or\n * `aria-labelledby` names it. Without one of those it's part of the name\n * already, so it isn't read twice.\n */\n description?: React.ReactNode;\n /**\n * Anything else in the card, after the description, such as a price. A\n * label holds phrasing content only, so spans, images and links: a link\n * works and doesn't toggle the card, but a button or another input can't\n * go inside a label at all. It isn't read when the checkbox takes focus,\n * so put what a screen reader should hear in `title` and `description`.\n */\n children?: React.ReactNode;\n /**\n * Shows the checkbox at the start of the card. Without it, the card's\n * edge alone shows the selection, and it's thicker when checked, so the\n * selection never rests on color.\n */\n hasIndicator?: boolean;\n /** The color of the checkbox and of a checked card's edge. */\n color?: (typeof checkboxCardColors)[number];\n /**\n * Text color helper, on the card. The title and the children take it, and\n * the description keeps its own color.\n */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Whether the card is disabled. A disabled card dims, takes no clicks, and leaves the Tab order. */\n disabled?: boolean;\n /**\n * Shows the mixed state, as in a \"Select all\" card when some of what it\n * covers is checked. It's a look and an announcement only: `checked` is\n * still the value, and a click still toggles `checked`. Set to `true` or\n * `false`, it's controlled: a browser clears the mixed state on a click,\n * so the component sets it again from this prop after every click and\n * every render. Unset isn't `false`. The component leaves the input's own\n * `indeterminate` property alone, so a ref can set it, and going from set\n * to unset clears it once and hands it back. It has no HTML attribute, so\n * server-rendered markup can't carry it, and a mixed card renders unmixed\n * until hydration.\n */\n indeterminate?: boolean;\n /**\n * Additional CSS classes, on the outer `<label>`, the card. That's the\n * element that declares the `--bulma-checkbox-card-*` variables, and\n * Bulma's `--bulma-card-*` ones, so a class is how to set one: `style` and\n * the other input attributes go to the `<input>`. Name `.checkbox-card`\n * beside your class in the selector, so it beats the card's own\n * declaration whatever order the stylesheets load in. A `color` prop\n * declares the active color again on `.checkbox-card.is-<color>`, which\n * ties that selector, so leave `color` unset when a class sets it.\n */\n className?: string;\n}\n\n/**\n * The `CheckboxCard` component is a checkbox drawn as a card, with a title and a description, that toggles wherever you click it.\n *\n * It's a `<label>` around a real checkbox, so it sends its `value` with a\n * form and Space toggles it. The title names the checkbox and the\n * description describes it. Alone it's one choice; inside `Checkboxes` it\n * takes the group's name and selection, as `Checkbox` does.\n *\n * @function\n * @param {CheckboxCardProps} props - Props for the CheckboxCard component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the `<input>`.\n * @returns {JSX.Element} The rendered card.\n *\n * @example\n * <Checkboxes label=\"Add-ons\" name=\"extras\" defaultValue={['backups']}>\n * <CheckboxCard value=\"backups\" title=\"Daily backups\" description=\"Kept for 30 days.\" />\n * <CheckboxCard value=\"domain\" title=\"Custom domain\" description=\"Bring your own.\" />\n * </Checkboxes>\n */\nexport const CheckboxCard = forwardRef<HTMLInputElement, CheckboxCardProps>(\n (\n {\n title,\n description,\n children,\n hasIndicator = true,\n color,\n className,\n textColor,\n disabled: disabledProp,\n name,\n value,\n checked,\n defaultChecked,\n indeterminate,\n onChange,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n ...props,\n });\n\n // The input's own ref, merged with the forwarded one, as Checkbox does,\n // so the mixed state can be set on it.\n const inputRef = useRef<HTMLInputElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') return ref(node);\n if (ref) ref.current = node;\n },\n [ref]\n );\n\n // `indeterminate` is a DOM property with no attribute, and a click clears\n // it, so it's set after every render while the prop is set, and cleared\n // once when the prop goes back to unset. Checkbox does the same.\n const ownsIndeterminateRef = useRef(false);\n useClientLayoutEffect(() => {\n if (indeterminate !== undefined) {\n ownsIndeterminateRef.current = true;\n inputRef.current!.indeterminate = indeterminate;\n } else if (ownsIndeterminateRef.current) {\n ownsIndeterminateRef.current = false;\n inputRef.current!.indeterminate = false;\n }\n });\n\n // A surrounding <Checkboxes> hands down its name and, when it manages\n // the selection, whether this card's value is in it. The card's own\n // props win, as they do on Checkbox.\n const group = useCheckboxesGroup();\n const effectiveName = name ?? group?.name;\n const groupManaged = group?.value !== undefined && value !== undefined;\n const effectiveChecked =\n checked !== undefined\n ? checked\n : groupManaged\n ? group!.value!.includes(String(value))\n : undefined;\n const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (indeterminate !== undefined) e.target.indeterminate = indeterminate;\n onChange?.(e);\n if (group?.onChange && value !== undefined) {\n const valStr = String(value);\n const current = group.value ?? [];\n group.onChange(\n e.target.checked\n ? current.includes(valStr)\n ? current\n : [...current, valStr]\n : current.filter(v => v !== valStr)\n );\n }\n },\n [onChange, group, value, indeterminate]\n );\n\n // The title names the input and the description describes it. A name\n // passed in wins, and without one of either the label's own text names\n // the input, description included, so it isn't described again.\n const titleId = useId();\n const descriptionId = useId();\n const ariaLabel = rest['aria-label'];\n const ariaLabelledBy =\n rest['aria-labelledby'] || (!ariaLabel && title ? titleId : undefined);\n const ariaDescribedBy =\n rest['aria-describedby'] ||\n (description && (ariaLabel || ariaLabelledBy)\n ? descriptionId\n : undefined);\n\n const cardClass = usePrefixedClassNames('checkbox-card', 'card', {\n [`is-${color}`]: color && checkboxCardColors.includes(color),\n });\n const contentClass = usePrefixedClassNames(\n 'card-content',\n 'checkbox-card-content'\n );\n const checkClass = usePrefixedClassNames('checkbox-card-check');\n const bodyClass = usePrefixedClassNames('checkbox-card-body');\n const titleClass = usePrefixedClassNames('checkbox-card-title');\n const descriptionClass = usePrefixedClassNames('checkbox-card-description');\n\n return (\n <label className={classNames(cardClass, bulmaHelperClasses, className)}>\n <input\n ref={setRefs}\n type=\"checkbox\"\n disabled={disabled}\n name={effectiveName}\n value={value}\n checked={effectiveChecked}\n defaultChecked={effectiveDefaultChecked}\n onChange={handleChange}\n {...rest}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n />\n <span className={contentClass}>\n {hasIndicator && <span className={checkClass} />}\n <span className={bodyClass}>\n {title ? (\n <span id={titleId} className={titleClass}>\n {title}\n </span>\n ) : null}\n {description ? (\n <span id={descriptionId} className={descriptionClass}>\n {description}\n </span>\n ) : null}\n {children}\n </span>\n </span>\n </label>\n );\n }\n);\n\nCheckboxCard.displayName = 'CheckboxCard';\n\nexport default CheckboxCard;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CheckboxCard.js","sources":["../../../src/form/CheckboxCard.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useId, useRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport {\n useCheckboxesGroup,\n useFieldsetDisabled,\n useRegisterChecked,\n} from './FormContext';\n\n// The colors `Checkbox` takes, as `checkboxColors` lists them. Declared here as\n// well, so the API page can read them off this module, and a type test holds\n// the two lists to each other.\nconst checkboxCardColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n\n/**\n * Props for the CheckboxCard component.\n *\n * @helperProps Helper props go on the outer `<label>`, the `.card`, with\n * `className`. The other attributes go on the `<input>`.\n * @extraProp {string} [name] - The form field name. Inside `Checkboxes`, the group's `name` when this is unset.\n * @extraProp {string} [value] - What a form sends for the card when it's checked. Inside a `Checkboxes` group that takes `value`, `defaultValue` or `onChange`, the card is checked while the group's value holds it. A group given only `onChange` starts from the cards' own `defaultChecked`.\n */\nexport interface CheckboxCardProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'color' | 'title'\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /**\n * What the option is, such as \"Daily backups\". It names the checkbox, so\n * a screen reader says it with the state. Without it, the card's whole\n * text names the checkbox, as a label's text does.\n */\n title?: React.ReactNode;\n /**\n * A line or two about the option, read after the name and the state. It's\n * the checkbox's description when `title`, `aria-label` or\n * `aria-labelledby` names it. Without one of those it's part of the name\n * already, so it isn't read twice.\n */\n description?: React.ReactNode;\n /**\n * Anything else in the card, after the description, such as a price. A\n * label holds phrasing content only, so spans, images and links: a link\n * works and doesn't toggle the card, but a button or another input can't\n * go inside a label at all. It isn't read when the checkbox takes focus,\n * so put what a screen reader should hear in `title` and `description`.\n */\n children?: React.ReactNode;\n /**\n * Shows the checkbox at the start of the card. Without it, the card's\n * edge alone shows the selection, and it's thicker when checked, so the\n * selection never rests on color.\n */\n hasIndicator?: boolean;\n /** The color of the checkbox and of a checked card's edge. */\n color?: (typeof checkboxCardColors)[number];\n /**\n * Text color helper, on the card. The title and the children take it, and\n * the description keeps its own color.\n */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Whether the card is disabled. A disabled card dims, takes no clicks, and leaves the Tab order. */\n disabled?: boolean;\n /**\n * Shows the mixed state, as in a \"Select all\" card when some of what it\n * covers is checked. It's a look and an announcement only: `checked` is\n * still the value, and a click still toggles `checked`. Set to `true` or\n * `false`, it's controlled: a browser clears the mixed state on a click,\n * so the component sets it again from this prop after every click and\n * every render. Unset isn't `false`. The component leaves the input's own\n * `indeterminate` property alone, so a ref can set it, and going from set\n * to unset clears it once and hands it back. It has no HTML attribute, so\n * server-rendered markup can't carry it, and a mixed card renders unmixed\n * until hydration.\n */\n indeterminate?: boolean;\n /**\n * Additional CSS classes, on the outer `<label>`, the card. That's the\n * element that declares the `--bulma-checkbox-card-*` variables, and\n * Bulma's `--bulma-card-*` ones, so a class is how to set one: `style` and\n * the other input attributes go to the `<input>`. Name `.checkbox-card`\n * beside your class in the selector, so it beats the card's own\n * declaration whatever order the stylesheets load in. A `color` prop\n * declares the active color again on `.checkbox-card.is-<color>`, which\n * ties that selector, so leave `color` unset when a class sets it.\n */\n className?: string;\n}\n\n/**\n * The `CheckboxCard` component is a checkbox drawn as a card, with a title and a description, that toggles wherever you click it.\n *\n * It's a `<label>` around a real checkbox, so it sends its `value` with a\n * form and Space toggles it. The title names the checkbox and the\n * description describes it. Alone it's one choice; inside `Checkboxes` it\n * takes the group's name and selection, as `Checkbox` does.\n *\n * @function\n * @param {CheckboxCardProps} props - Props for the CheckboxCard component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the `<input>`.\n * @returns {JSX.Element} The rendered card.\n *\n * @example\n * <Checkboxes label=\"Add-ons\" name=\"extras\" defaultValue={['backups']}>\n * <CheckboxCard value=\"backups\" title=\"Daily backups\" description=\"Kept for 30 days.\" />\n * <CheckboxCard value=\"domain\" title=\"Custom domain\" description=\"Bring your own.\" />\n * </Checkboxes>\n */\nexport const CheckboxCard = forwardRef<HTMLInputElement, CheckboxCardProps>(\n (\n {\n title,\n description,\n children,\n hasIndicator = true,\n color,\n className,\n textColor,\n disabled: disabledProp,\n name,\n value,\n checked,\n defaultChecked,\n indeterminate,\n onChange,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n ...props,\n });\n\n // The input's own ref, merged with the forwarded one, as Checkbox does,\n // so the mixed state can be set on it.\n const inputRef = useRef<HTMLInputElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') return ref(node);\n if (ref) ref.current = node;\n },\n [ref]\n );\n\n // `indeterminate` is a DOM property with no attribute, and a click clears\n // it, so it's set after every render while the prop is set, and cleared\n // once when the prop goes back to unset. Checkbox does the same.\n const ownsIndeterminateRef = useRef(false);\n useClientLayoutEffect(() => {\n if (indeterminate !== undefined) {\n ownsIndeterminateRef.current = true;\n inputRef.current!.indeterminate = indeterminate;\n } else if (ownsIndeterminateRef.current) {\n ownsIndeterminateRef.current = false;\n inputRef.current!.indeterminate = false;\n }\n });\n\n // A surrounding <Checkboxes> hands down its name and, when it manages\n // the selection, whether this card's value is in it. The card's own\n // props win, as they do on Checkbox. A group given only `onChange` holds\n // no value until its first change, and until then the card shows its own\n // `defaultChecked`, controlled all the same, and registers it, so that\n // change starts from what was checked, as Checkbox does.\n const group = useCheckboxesGroup();\n const effectiveName = name ?? group?.name;\n const valueKey = value === undefined ? undefined : String(value);\n const groupManaged =\n group?.onChange !== undefined && valueKey !== undefined;\n const effectiveChecked =\n checked !== undefined\n ? checked\n : groupManaged\n ? group!.value\n ? group!.value.includes(valueKey!)\n : !!defaultChecked\n : undefined;\n const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;\n useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (indeterminate !== undefined) e.target.indeterminate = indeterminate;\n onChange?.(e);\n if (group?.onChange && valueKey !== undefined) {\n const current = group.value ?? group.startingValue!();\n group.onChange(\n e.target.checked\n ? current.includes(valueKey)\n ? current\n : [...current, valueKey]\n : current.filter(v => v !== valueKey)\n );\n }\n },\n [onChange, group, valueKey, indeterminate]\n );\n\n // The title names the input and the description describes it. A name\n // passed in wins, and without one of either the label's own text names\n // the input, description included, so it isn't described again.\n const titleId = useId();\n const descriptionId = useId();\n const ariaLabel = rest['aria-label'];\n const ariaLabelledBy =\n rest['aria-labelledby'] || (!ariaLabel && title ? titleId : undefined);\n const ariaDescribedBy =\n rest['aria-describedby'] ||\n (description && (ariaLabel || ariaLabelledBy)\n ? descriptionId\n : undefined);\n\n const cardClass = usePrefixedClassNames('checkbox-card', 'card', {\n [`is-${color}`]: color && checkboxCardColors.includes(color),\n });\n const contentClass = usePrefixedClassNames(\n 'card-content',\n 'checkbox-card-content'\n );\n const checkClass = usePrefixedClassNames('checkbox-card-check');\n const bodyClass = usePrefixedClassNames('checkbox-card-body');\n const titleClass = usePrefixedClassNames('checkbox-card-title');\n const descriptionClass = usePrefixedClassNames('checkbox-card-description');\n\n return (\n <label className={classNames(cardClass, bulmaHelperClasses, className)}>\n <input\n ref={setRefs}\n type=\"checkbox\"\n disabled={disabled}\n name={effectiveName}\n value={value}\n checked={effectiveChecked}\n defaultChecked={effectiveDefaultChecked}\n onChange={handleChange}\n {...rest}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n />\n <span className={contentClass}>\n {hasIndicator && <span className={checkClass} />}\n <span className={bodyClass}>\n {title ? (\n <span id={titleId} className={titleClass}>\n {title}\n </span>\n ) : null}\n {description ? (\n <span id={descriptionId} className={descriptionClass}>\n {description}\n </span>\n ) : null}\n {children}\n </span>\n </span>\n </label>\n );\n }\n);\n\nCheckboxCard.displayName = 'CheckboxCard';\n\nexport default CheckboxCard;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
2
|
'use client';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import { useState, useCallback, useMemo } from 'react';
|
|
4
|
+
import { useState, useCallback, useRef, useMemo } from 'react';
|
|
5
5
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
6
6
|
import { withSubComponents } from '../helpers/withSubComponents.js';
|
|
7
7
|
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
@@ -76,10 +76,37 @@ const CheckboxesComponent = ({ label, labelSize, labelProps, horizontal, message
|
|
|
76
76
|
setInternalValue(newValues);
|
|
77
77
|
onChange?.(newValues);
|
|
78
78
|
}, [isControlled, onChange]);
|
|
79
|
+
// A group given only `onChange` holds no value until its first change. The
|
|
80
|
+
// choices register the values they start checked with, so that change
|
|
81
|
+
// starts from what was checked rather than from an empty array. A ref, not
|
|
82
|
+
// state: nothing renders from it.
|
|
83
|
+
const startingRef = useRef(new Map());
|
|
84
|
+
const registerChecked = useCallback((checkedValue) => {
|
|
85
|
+
const key = {};
|
|
86
|
+
startingRef.current.set(key, checkedValue);
|
|
87
|
+
return () => {
|
|
88
|
+
startingRef.current.delete(key);
|
|
89
|
+
};
|
|
90
|
+
}, []);
|
|
91
|
+
const startingValue = useCallback(() => Array.from(new Set(startingRef.current.values())), []);
|
|
79
92
|
const ctx = useMemo(() => ({
|
|
80
93
|
name,
|
|
81
|
-
...(groupActive
|
|
82
|
-
|
|
94
|
+
...(groupActive
|
|
95
|
+
? {
|
|
96
|
+
value: currentValue,
|
|
97
|
+
onChange: handleChange,
|
|
98
|
+
registerChecked,
|
|
99
|
+
startingValue,
|
|
100
|
+
}
|
|
101
|
+
: {}),
|
|
102
|
+
}), [
|
|
103
|
+
name,
|
|
104
|
+
groupActive,
|
|
105
|
+
currentValue,
|
|
106
|
+
handleChange,
|
|
107
|
+
registerChecked,
|
|
108
|
+
startingValue,
|
|
109
|
+
]);
|
|
83
110
|
const choices = (jsx(CheckboxesProvider, { value: ctx, children: children }));
|
|
84
111
|
// A fieldset is a group already, so it takes no role of its own.
|
|
85
112
|
const Group = asFieldset ? 'fieldset' : 'div';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkboxes.js","sources":["../../../src/form/Checkboxes.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n rendersOwnControl,\n CheckboxesProvider,\n CheckboxesGroupContextValue,\n} from './FormContext';\nimport { Field } from './Field';\nimport { Control } from './Control';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelledBy } from './useAutoLabelId';\nimport { Checkbox } from './Checkbox';\nimport { GroupFieldset } from './groupFieldset';\n\n/**\n * Props for the Checkboxes component.\n * Inside an existing `Control` it renders no `Control` of its own. Inside an\n * outer `Field`, or a `Control` with no `Field` around it, it renders no\n * `Field` of its own either. The exception is `label`, `message`, `horizontal`\n * or `fieldClassName` in that bare `Control`: it keeps a `Field` for them,\n * nested in the `.control`, and warns in development. Wrap the `Control` in a\n * `Field` instead, and set the `label`, `horizontal` and class name on that\n * `Field`.\n */\nexport interface CheckboxesProps\n extends Omit<BulmaClassesProps, 'color'>, FormFieldProps {\n /** Field label naming the whole group. Automatically associated via `aria-labelledby` on the `role=\"group\"` wrapper — uses your `labelProps.id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label names the group instead through `aria-labelledby` when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). An `aria-label` or `aria-labelledby` you set on the group wins over either label, which still renders but no longer names it. An `aria-labelledby` key counts even when undefined, since it is spread over the group's own. */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `id` here is used as the `aria-labelledby` target instead of a generated one; any `htmlFor` is ignored (a group label names the group, never a single control). */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Additional CSS classes to apply. */\n className?: string;\n /** Form field name shared by every Checkbox in the group (via context). */\n name?: string;\n /** Currently-selected values (controlled mode). */\n value?: string[];\n /** Initial selected values (uncontrolled mode). */\n defaultValue?: string[];\n /** Fires when the selection changes; receives the new array. */\n onChange?: (values: string[]) => void;\n /** Checkbox elements to render in the group. */\n children?: React.ReactNode;\n /**\n * The element the group renders as. With `fieldset` it's a native\n * `<fieldset>`. Where the group renders a `Field` of its own, that `Field`\n * is the `<fieldset>` and the `label` is its `<legend>`, in the label\n * column when `horizontal`, so the legend names the group with no ids to\n * wire. Your other attributes then go on the `<fieldset>`, while\n * `className` and the helper props stay on the box that lays out the\n * checkboxes. Inside an outer `Field` there's no legend: the group element\n * itself is the `<fieldset>`, named by that `Field`'s label as before.\n * `div`, the default, renders the group as it always has.\n * @defaultValue 'div'\n */\n as?: 'div' | 'fieldset';\n}\n\n/**\n * The `Checkboxes` component wraps multiple `Checkbox` components in a Bulma-styled group.\n *\n * @function\n * @param {CheckboxesProps} props - Props for the Checkboxes component.\n * @returns {JSX.Element} The rendered checkboxes group.\n * @see {@link https://bulma.io/documentation/form/checkbox/#grouped-checkboxes | Bulma Checkboxes documentation}\n *\n * @example\n * // Controlled\n * const [tags, setTags] = useState(['react']);\n * <Checkboxes name=\"tags\" value={tags} onChange={setTags}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * <Checkbox value=\"angular\">Angular</Checkbox>\n * </Checkboxes>\n *\n * @example\n * // Uncontrolled\n * <Checkboxes name=\"tags\" defaultValue={['react', 'vue']}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * <Checkbox value=\"angular\">Angular</Checkbox>\n * </Checkboxes>\n */\nconst CheckboxesComponent: React.FC<CheckboxesProps> = ({\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n name,\n value,\n defaultValue,\n onChange,\n children,\n className,\n as,\n ...props\n}) => {\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Checkboxes', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n // As a fieldset with a Field of its own, the group's label is its legend,\n // which names it with no id, so nothing points `aria-labelledby` at it.\n const asFieldset = as === 'fieldset';\n const fieldsetField = asFieldset && ownField;\n const { ariaLabelledBy, fieldLabelProps } = useAutoLabelledBy({\n label,\n labelProps,\n rendersLabel: ownField && !fieldsetField,\n callerProps: props,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('checkboxes');\n const wrapperClass = classNames(mainClass, bulmaHelperClasses, className);\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n const groupActive =\n value !== undefined || defaultValue !== undefined || onChange !== undefined;\n\n const [internalValue, setInternalValue] = useState<string[] | undefined>(\n defaultValue\n );\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : internalValue;\n\n const handleChange = useCallback(\n (newValues: string[]) => {\n if (!isControlled) setInternalValue(newValues);\n onChange?.(newValues);\n },\n [isControlled, onChange]\n );\n\n const ctx = useMemo<CheckboxesGroupContextValue>(\n () => ({\n name,\n ...(groupActive ? { value: currentValue, onChange: handleChange } : {}),\n }),\n [name, groupActive, currentValue, handleChange]\n );\n\n const choices = (\n <CheckboxesProvider value={ctx}>{children}</CheckboxesProvider>\n );\n // A fieldset is a group already, so it takes no role of its own.\n const Group = asFieldset ? 'fieldset' : 'div';\n const checkboxesElement = fieldsetField ? (\n <div className={wrapperClass}>{choices}</div>\n ) : (\n <Group\n className={wrapperClass}\n role={asFieldset ? undefined : 'group'}\n aria-labelledby={ariaLabelledBy}\n {...rest}\n >\n {choices}\n </Group>\n );\n\n let content = checkboxesElement;\n\n if (rendersOwnControl('Checkboxes', { insideControl })) {\n content = <Control>{content}</Control>;\n }\n\n if (fieldsetField) {\n return (\n <GroupFieldset\n label={label}\n labelSize={labelSize}\n labelProps={labelProps}\n horizontal={horizontal}\n fieldClassName={fieldClassName}\n attributes={rest}\n message={messageEl}\n >\n {content}\n </GroupFieldset>\n );\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 {content}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {content}\n {messageEl}\n </>\n );\n};\n\nexport const Checkboxes = withSubComponents(\n CheckboxesComponent,\n { Checkbox },\n 'Checkboxes'\n);\n\nexport default Checkboxes;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Checkboxes.js","sources":["../../../src/form/Checkboxes.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n rendersOwnControl,\n CheckboxesProvider,\n CheckboxesGroupContextValue,\n} from './FormContext';\nimport { Field } from './Field';\nimport { Control } from './Control';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelledBy } from './useAutoLabelId';\nimport { Checkbox } from './Checkbox';\nimport { GroupFieldset } from './groupFieldset';\n\n/**\n * Props for the Checkboxes component.\n * Inside an existing `Control` it renders no `Control` of its own. Inside an\n * outer `Field`, or a `Control` with no `Field` around it, it renders no\n * `Field` of its own either. The exception is `label`, `message`, `horizontal`\n * or `fieldClassName` in that bare `Control`: it keeps a `Field` for them,\n * nested in the `.control`, and warns in development. Wrap the `Control` in a\n * `Field` instead, and set the `label`, `horizontal` and class name on that\n * `Field`.\n */\nexport interface CheckboxesProps\n extends Omit<BulmaClassesProps, 'color'>, FormFieldProps {\n /** Field label naming the whole group. Automatically associated via `aria-labelledby` on the `role=\"group\"` wrapper — uses your `labelProps.id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label names the group instead through `aria-labelledby` when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). An `aria-label` or `aria-labelledby` you set on the group wins over either label, which still renders but no longer names it. An `aria-labelledby` key counts even when undefined, since it is spread over the group's own. */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `id` here is used as the `aria-labelledby` target instead of a generated one; any `htmlFor` is ignored (a group label names the group, never a single control). */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Additional CSS classes to apply. */\n className?: string;\n /** Form field name shared by every Checkbox in the group (via context). */\n name?: string;\n /** Currently-selected values (controlled mode). */\n value?: string[];\n /** Initial selected values (uncontrolled mode). */\n defaultValue?: string[];\n /**\n * Fires when the selection changes; receives the new array. Passed without\n * `value` or `defaultValue`, it still has the group manage the selection,\n * starting from the checkboxes' own `defaultChecked`: a box that starts\n * checked stays checked when another is clicked, and the first array holds\n * it.\n */\n onChange?: (values: string[]) => void;\n /** Checkbox elements to render in the group. */\n children?: React.ReactNode;\n /**\n * The element the group renders as. With `fieldset` it's a native\n * `<fieldset>`. Where the group renders a `Field` of its own, that `Field`\n * is the `<fieldset>` and the `label` is its `<legend>`, in the label\n * column when `horizontal`, so the legend names the group with no ids to\n * wire. Your other attributes then go on the `<fieldset>`, while\n * `className` and the helper props stay on the box that lays out the\n * checkboxes. Inside an outer `Field` there's no legend: the group element\n * itself is the `<fieldset>`, named by that `Field`'s label as before.\n * `div`, the default, renders the group as it always has.\n * @defaultValue 'div'\n */\n as?: 'div' | 'fieldset';\n}\n\n/**\n * The `Checkboxes` component wraps multiple `Checkbox` components in a Bulma-styled group.\n *\n * @function\n * @param {CheckboxesProps} props - Props for the Checkboxes component.\n * @returns {JSX.Element} The rendered checkboxes group.\n * @see {@link https://bulma.io/documentation/form/checkbox/#grouped-checkboxes | Bulma Checkboxes documentation}\n *\n * @example\n * // Controlled\n * const [tags, setTags] = useState(['react']);\n * <Checkboxes name=\"tags\" value={tags} onChange={setTags}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * <Checkbox value=\"angular\">Angular</Checkbox>\n * </Checkboxes>\n *\n * @example\n * // Uncontrolled\n * <Checkboxes name=\"tags\" defaultValue={['react', 'vue']}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * <Checkbox value=\"angular\">Angular</Checkbox>\n * </Checkboxes>\n */\nconst CheckboxesComponent: React.FC<CheckboxesProps> = ({\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n name,\n value,\n defaultValue,\n onChange,\n children,\n className,\n as,\n ...props\n}) => {\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Checkboxes', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n // As a fieldset with a Field of its own, the group's label is its legend,\n // which names it with no id, so nothing points `aria-labelledby` at it.\n const asFieldset = as === 'fieldset';\n const fieldsetField = asFieldset && ownField;\n const { ariaLabelledBy, fieldLabelProps } = useAutoLabelledBy({\n label,\n labelProps,\n rendersLabel: ownField && !fieldsetField,\n callerProps: props,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n ...props,\n });\n\n const mainClass = usePrefixedClassNames('checkboxes');\n const wrapperClass = classNames(mainClass, bulmaHelperClasses, className);\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n const groupActive =\n value !== undefined || defaultValue !== undefined || onChange !== undefined;\n\n const [internalValue, setInternalValue] = useState<string[] | undefined>(\n defaultValue\n );\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : internalValue;\n\n const handleChange = useCallback(\n (newValues: string[]) => {\n if (!isControlled) setInternalValue(newValues);\n onChange?.(newValues);\n },\n [isControlled, onChange]\n );\n\n // A group given only `onChange` holds no value until its first change. The\n // choices register the values they start checked with, so that change\n // starts from what was checked rather than from an empty array. A ref, not\n // state: nothing renders from it.\n const startingRef = useRef(new Map<object, string>());\n const registerChecked = useCallback((checkedValue: string) => {\n const key = {};\n startingRef.current.set(key, checkedValue);\n return () => {\n startingRef.current.delete(key);\n };\n }, []);\n const startingValue = useCallback(\n () => Array.from(new Set(startingRef.current.values())),\n []\n );\n\n const ctx = useMemo<CheckboxesGroupContextValue>(\n () => ({\n name,\n ...(groupActive\n ? {\n value: currentValue,\n onChange: handleChange,\n registerChecked,\n startingValue,\n }\n : {}),\n }),\n [\n name,\n groupActive,\n currentValue,\n handleChange,\n registerChecked,\n startingValue,\n ]\n );\n\n const choices = (\n <CheckboxesProvider value={ctx}>{children}</CheckboxesProvider>\n );\n // A fieldset is a group already, so it takes no role of its own.\n const Group = asFieldset ? 'fieldset' : 'div';\n const checkboxesElement = fieldsetField ? (\n <div className={wrapperClass}>{choices}</div>\n ) : (\n <Group\n className={wrapperClass}\n role={asFieldset ? undefined : 'group'}\n aria-labelledby={ariaLabelledBy}\n {...rest}\n >\n {choices}\n </Group>\n );\n\n let content = checkboxesElement;\n\n if (rendersOwnControl('Checkboxes', { insideControl })) {\n content = <Control>{content}</Control>;\n }\n\n if (fieldsetField) {\n return (\n <GroupFieldset\n label={label}\n labelSize={labelSize}\n labelProps={labelProps}\n horizontal={horizontal}\n fieldClassName={fieldClassName}\n attributes={rest}\n message={messageEl}\n >\n {content}\n </GroupFieldset>\n );\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 {content}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {content}\n {messageEl}\n </>\n );\n};\n\nexport const Checkboxes = withSubComponents(\n CheckboxesComponent,\n { Checkbox },\n 'Checkboxes'\n);\n\nexport default Checkboxes;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|