@allxsmith/bestax-bulma 5.26.0 → 5.26.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/index.cjs +80 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +80 -28
- package/dist/index.esm.js.map +1 -1
- package/dist/types/form/DateInputBase.d.ts +6 -1
- package/dist/types/form/DateTimeInputBase.d.ts +6 -1
- package/dist/types/form/TimeInputBase.d.ts +6 -1
- package/dist/types/form/_pickerInternals/PickerPopover.d.ts +7 -0
- package/dist/types/form/_pickerInternals/useSegmentedEntry.d.ts +5 -0
- package/dist/types/helpers/Theme.d.ts +9 -0
- package/dist/types-cjs/form/DateInputBase.d.ts +6 -1
- package/dist/types-cjs/form/DateTimeInputBase.d.ts +6 -1
- package/dist/types-cjs/form/TimeInputBase.d.ts +6 -1
- package/dist/types-cjs/form/_pickerInternals/PickerPopover.d.ts +7 -0
- package/dist/types-cjs/form/_pickerInternals/useSegmentedEntry.d.ts +5 -0
- package/dist/types-cjs/helpers/Theme.d.ts +9 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -12192,7 +12192,7 @@ const Calendar = ({ value, focusedDate, onSelect, onFocusedDateChange, min, max,
|
|
|
12192
12192
|
Calendar.displayName = 'Calendar';
|
|
12193
12193
|
|
|
12194
12194
|
const isBrowser = typeof window !== 'undefined';
|
|
12195
|
-
const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'bottom-left', appendToBody = false, className, trapFocus = true, closeOnClickOutside = true, closeOnEscape = true, ariaLabel, ariaLabelledBy, role = 'dialog', id, }) => {
|
|
12195
|
+
const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'bottom-left', appendToBody = false, className, trapFocus = true, closeOnClickOutside = true, closeOnEscape = true, ariaLabel, ariaLabelledBy, role = 'dialog', id, restoreFocusRef, }) => {
|
|
12196
12196
|
const panelRef = React.useRef(null);
|
|
12197
12197
|
const resolved = useAnchoredPosition(anchorRef, panelRef, {
|
|
12198
12198
|
active: isOpen,
|
|
@@ -12229,7 +12229,10 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'botto
|
|
|
12229
12229
|
document.addEventListener('keydown', handler);
|
|
12230
12230
|
return () => document.removeEventListener('keydown', handler);
|
|
12231
12231
|
}, [isOpen, closeOnEscape, onClose]);
|
|
12232
|
-
useFocusTrap(panelRef, {
|
|
12232
|
+
useFocusTrap(panelRef, {
|
|
12233
|
+
active: isOpen && trapFocus,
|
|
12234
|
+
restoreFocus: restoreFocusRef ?? true,
|
|
12235
|
+
});
|
|
12233
12236
|
const panelClass = usePrefixedClassNames('picker-popover', {
|
|
12234
12237
|
'is-active': isOpen,
|
|
12235
12238
|
[`is-${resolved.position}`]: true,
|
|
@@ -12634,6 +12637,37 @@ function useSegmentedEntry(params) {
|
|
|
12634
12637
|
// change. Kept in a ref because key handlers read+update synchronously
|
|
12635
12638
|
// within the same event tick.
|
|
12636
12639
|
const typedDigitsRef = React.useRef('');
|
|
12640
|
+
// The text focus seeded an empty picker with, until the user edits it or
|
|
12641
|
+
// leaves. While the text still matches it, nothing has been typed.
|
|
12642
|
+
const seedRef = React.useRef(null);
|
|
12643
|
+
// Whether the input's current focus is the one a closing popover handed
|
|
12644
|
+
// back, until focus leaves the picker.
|
|
12645
|
+
const handedBackRef = React.useRef(false);
|
|
12646
|
+
// A seed the popover never turned into a value closes with it, wherever
|
|
12647
|
+
// focus goes, so a dismissed empty field stays empty.
|
|
12648
|
+
//
|
|
12649
|
+
// As the popover closes, its focus trap hands focus back to the input. That
|
|
12650
|
+
// focus is not the user arriving: it must not open the popover again under
|
|
12651
|
+
// `openOnFocus`, or seed an empty picker that leaving would then commit.
|
|
12652
|
+
// `closingRef` is set in the layout phase of the commit that closes it and
|
|
12653
|
+
// cleared by that commit's effects, and React runs a commit's effect
|
|
12654
|
+
// cleanups, the trap's among them, before any of its effects, so a focus
|
|
12655
|
+
// in between is the one handed back.
|
|
12656
|
+
const closingRef = React.useRef(false);
|
|
12657
|
+
const wasOpenRef = React.useRef(isOpen);
|
|
12658
|
+
React.useLayoutEffect(() => {
|
|
12659
|
+
if (wasOpenRef.current && !isOpen) {
|
|
12660
|
+
closingRef.current = true;
|
|
12661
|
+
if (!value && seedRef.current !== null && text === seedRef.current) {
|
|
12662
|
+
setText('');
|
|
12663
|
+
}
|
|
12664
|
+
seedRef.current = null;
|
|
12665
|
+
}
|
|
12666
|
+
wasOpenRef.current = isOpen;
|
|
12667
|
+
}, [isOpen, value, text, setText]);
|
|
12668
|
+
React.useEffect(() => {
|
|
12669
|
+
closingRef.current = false;
|
|
12670
|
+
}, [isOpen]);
|
|
12637
12671
|
// Segment mode is unavailable for disabled / read-only / non-editable
|
|
12638
12672
|
// pickers and for Intl-options / variable-width formats (segmentMap null).
|
|
12639
12673
|
const segmentEditable = !!segmentMap && !!editable && !disabled && !readOnly;
|
|
@@ -12690,6 +12724,7 @@ function useSegmentedEntry(params) {
|
|
|
12690
12724
|
// segment mode is inactive.
|
|
12691
12725
|
if (activeSegmentIdx !== null && segmentEditable)
|
|
12692
12726
|
return;
|
|
12727
|
+
seedRef.current = null;
|
|
12693
12728
|
setText(e.target.value);
|
|
12694
12729
|
}, [activeSegmentIdx, segmentEditable, setText]);
|
|
12695
12730
|
const handleBlur = React.useCallback((e) => {
|
|
@@ -12707,6 +12742,16 @@ function useSegmentedEntry(params) {
|
|
|
12707
12742
|
}
|
|
12708
12743
|
setActiveSegmentIdx(null);
|
|
12709
12744
|
typedDigitsRef.current = '';
|
|
12745
|
+
seedRef.current = null;
|
|
12746
|
+
const handedBack = handedBackRef.current;
|
|
12747
|
+
handedBackRef.current = false;
|
|
12748
|
+
// Leaving after a dismiss commits only what was typed since. Text that
|
|
12749
|
+
// still shows the value wasn't, and re-parsing it could drop what the
|
|
12750
|
+
// format leaves out, such as seconds.
|
|
12751
|
+
if (handedBack && value && text === formatFn(value, format, locale)) {
|
|
12752
|
+
onBlur?.(e);
|
|
12753
|
+
return;
|
|
12754
|
+
}
|
|
12710
12755
|
const parsed = tryParse(text);
|
|
12711
12756
|
if (parsed && isAllowed(parsed)) {
|
|
12712
12757
|
commitValue(parsed);
|
|
@@ -12729,13 +12774,19 @@ function useSegmentedEntry(params) {
|
|
|
12729
12774
|
onBlur,
|
|
12730
12775
|
]);
|
|
12731
12776
|
const handleFocus = React.useCallback((e) => {
|
|
12732
|
-
|
|
12777
|
+
const handedBack = closingRef.current;
|
|
12778
|
+
handedBackRef.current = handedBack;
|
|
12779
|
+
if (!handedBack && openOnFocus && popover && !disabled && !readOnly) {
|
|
12733
12780
|
setOpen(true);
|
|
12781
|
+
}
|
|
12734
12782
|
// Enter segment mode: prime an initial value (so editing works even when
|
|
12735
|
-
// empty), seed the text, and highlight the first editable segment.
|
|
12783
|
+
// empty), seed the text, and highlight the first editable segment. The
|
|
12784
|
+
// segment base doesn't need the seed, so focus handed back skips it.
|
|
12736
12785
|
if (segmentEditable && segmentMap) {
|
|
12737
|
-
if (!value) {
|
|
12738
|
-
|
|
12786
|
+
if (!value && !handedBack) {
|
|
12787
|
+
const seed = formatFn(makeBaseDate(), format, locale);
|
|
12788
|
+
seedRef.current = seed;
|
|
12789
|
+
setText(seed);
|
|
12739
12790
|
}
|
|
12740
12791
|
typedDigitsRef.current = '';
|
|
12741
12792
|
setActiveSegmentIdx(segmentMap.editable[0]);
|
|
@@ -13202,7 +13253,7 @@ const DateInputBase = React.forwardRef((props, ref) => {
|
|
|
13202
13253
|
return (jsxRuntime.jsxs("div", { ref: containerRef, className: classNames(containerClass, bulmaHelperClasses, className), ...cleanRest, children: [jsxRuntime.jsx("input", { ref: combinedRef, type: "text", role: "combobox", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": popoverId, autoComplete: "off", className: inputClass, value: text, placeholder: placeholder, disabled: disabled, readOnly: inputReadOnlyAttr, name: name, form: form, required: required, id: id, ...inputHandlers }), popover && triggerIcon && (jsxRuntime.jsx("button", { type: "button", className: triggerClass, onClick: () => {
|
|
13203
13254
|
if (canOpen)
|
|
13204
13255
|
setOpen(!open);
|
|
13205
|
-
}, disabled: !canOpen, "aria-label": chooseLabel, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsxRuntime.jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsxRuntime.jsx(PickerPopover, { isOpen: open, onClose: handlePopoverClose, anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: chooseLabel, id: popoverId, children: calendar }))] }));
|
|
13256
|
+
}, disabled: !canOpen, "aria-label": chooseLabel, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsxRuntime.jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsxRuntime.jsx(PickerPopover, { isOpen: open, onClose: handlePopoverClose, anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: chooseLabel, id: popoverId, restoreFocusRef: inputRef, children: calendar }))] }));
|
|
13206
13257
|
});
|
|
13207
13258
|
DateInputBase.displayName = 'DateInputBase';
|
|
13208
13259
|
|
|
@@ -14175,9 +14226,6 @@ const TimeInputBase = React.forwardRef((props, ref) => {
|
|
|
14175
14226
|
const mobileFooterClass = usePrefixedClassNames('timeinput-footer-mobile');
|
|
14176
14227
|
const mobileFooterResetClass = usePrefixedClassNames('timeinput-footer-reset');
|
|
14177
14228
|
const mobileFooterDoneClass = usePrefixedClassNames('timeinput-footer-done');
|
|
14178
|
-
// Set from the moment the popover starts to close until the close has
|
|
14179
|
-
// committed. See `setOpenFromInput`.
|
|
14180
|
-
const closingRef = React.useRef(false);
|
|
14181
14229
|
const setOpen = React.useCallback((next) => {
|
|
14182
14230
|
setOpenState(prev => {
|
|
14183
14231
|
if (prev === next)
|
|
@@ -14187,26 +14235,11 @@ const TimeInputBase = React.forwardRef((props, ref) => {
|
|
|
14187
14235
|
onOpen?.();
|
|
14188
14236
|
}
|
|
14189
14237
|
else {
|
|
14190
|
-
closingRef.current = true;
|
|
14191
14238
|
onClose?.();
|
|
14192
14239
|
}
|
|
14193
14240
|
return next;
|
|
14194
14241
|
});
|
|
14195
14242
|
}, [onOpen, onClose, value]);
|
|
14196
|
-
// React runs a commit's effect cleanups before any of its effects, so on a
|
|
14197
|
-
// close this runs after the popover's focus trap has handed focus back.
|
|
14198
|
-
React.useEffect(() => {
|
|
14199
|
-
closingRef.current = false;
|
|
14200
|
-
}, [open]);
|
|
14201
|
-
// As the popover closes, its focus trap hands focus back to the input.
|
|
14202
|
-
// That focus is not the user arriving, so under `openOnFocus` it must not
|
|
14203
|
-
// open the popover again. The input asks to open only on focus, click or
|
|
14204
|
-
// ArrowDown, so a request while a close commits can only be that one.
|
|
14205
|
-
const setOpenFromInput = React.useCallback((next) => {
|
|
14206
|
-
if (next && closingRef.current)
|
|
14207
|
-
return;
|
|
14208
|
-
setOpen(next);
|
|
14209
|
-
}, [setOpen]);
|
|
14210
14243
|
React.useEffect(() => {
|
|
14211
14244
|
setText(value ? formatTime(value, defaultFormat, locale) : '');
|
|
14212
14245
|
}, [value, defaultFormat, locale]);
|
|
@@ -14263,7 +14296,7 @@ const TimeInputBase = React.forwardRef((props, ref) => {
|
|
|
14263
14296
|
openOnFocus,
|
|
14264
14297
|
closeOnSelect,
|
|
14265
14298
|
isOpen: open,
|
|
14266
|
-
setOpen
|
|
14299
|
+
setOpen,
|
|
14267
14300
|
inputRef,
|
|
14268
14301
|
containerRef,
|
|
14269
14302
|
onFocus,
|
|
@@ -14315,7 +14348,7 @@ const TimeInputBase = React.forwardRef((props, ref) => {
|
|
|
14315
14348
|
return (jsxRuntime.jsxs("div", { ref: containerRef, className: classNames(containerClass, bulmaHelperClasses, className), ...cleanRest, children: [jsxRuntime.jsx("input", { ref: combinedRef, type: "text", role: "combobox", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": popoverId, autoComplete: "off", className: inputClass, value: text, placeholder: placeholder, disabled: disabled, readOnly: inputReadOnlyAttr, name: name, form: form, required: required, id: id, ...inputHandlers }), popover && triggerIcon && (jsxRuntime.jsx("button", { type: "button", className: triggerClass, onClick: () => {
|
|
14316
14349
|
if (canOpen)
|
|
14317
14350
|
setOpen(!open);
|
|
14318
|
-
}, disabled: !canOpen, "aria-label": t.chooseTime, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsxRuntime.jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsxRuntime.jsx(PickerPopover, { isOpen: open, onClose: () => setOpen(false), anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: t.chooseTime, id: popoverId, children: panel }))] }));
|
|
14351
|
+
}, disabled: !canOpen, "aria-label": t.chooseTime, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsxRuntime.jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsxRuntime.jsx(PickerPopover, { isOpen: open, onClose: () => setOpen(false), anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: t.chooseTime, id: popoverId, restoreFocusRef: inputRef, children: panel }))] }));
|
|
14319
14352
|
});
|
|
14320
14353
|
TimeInputBase.displayName = 'TimeInputBase';
|
|
14321
14354
|
|
|
@@ -14607,7 +14640,7 @@ const DateTimeInputBase = React.forwardRef((props, ref) => {
|
|
|
14607
14640
|
return (jsxRuntime.jsxs("div", { ref: containerRef, className: classNames(containerClass, bulmaHelperClasses, className), ...cleanRest, children: [jsxRuntime.jsx("input", { ref: combinedRef, type: "text", role: "combobox", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": popoverId, autoComplete: "off", className: inputClass, value: text, placeholder: placeholder, disabled: disabled, readOnly: inputReadOnlyAttr, name: name, form: form, required: required, id: id, ...inputHandlers }), popover && triggerIcon && (jsxRuntime.jsx("button", { type: "button", className: triggerClass, onClick: () => {
|
|
14608
14641
|
if (canOpen)
|
|
14609
14642
|
setOpen(!open);
|
|
14610
|
-
}, disabled: !canOpen, "aria-label": t.chooseDateTime, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsxRuntime.jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsxRuntime.jsx(PickerPopover, { isOpen: open, onClose: () => setOpen(false), anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: t.chooseDateTime, id: popoverId, children: panel }))] }));
|
|
14643
|
+
}, disabled: !canOpen, "aria-label": t.chooseDateTime, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsxRuntime.jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsxRuntime.jsx(PickerPopover, { isOpen: open, onClose: () => setOpen(false), anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: t.chooseDateTime, id: popoverId, restoreFocusRef: inputRef, children: panel }))] }));
|
|
14611
14644
|
});
|
|
14612
14645
|
DateTimeInputBase.displayName = 'DateTimeInputBase';
|
|
14613
14646
|
|
|
@@ -15524,6 +15557,25 @@ const Theme = ({ bulmaVars = {}, children, className, isRoot = false, colorMode,
|
|
|
15524
15557
|
}
|
|
15525
15558
|
return { bulmaVarProps: varProps, otherProps: otherPropsObj };
|
|
15526
15559
|
}, [restProps]);
|
|
15560
|
+
// Everything left in `otherProps` lands on the wrapper div, as a helper
|
|
15561
|
+
// class or an attribute, and so does `className`. A root Theme renders no
|
|
15562
|
+
// wrapper, so under `isRoot` all of it is dropped. `radius` and `columnGap`
|
|
15563
|
+
// are not in `otherProps`; the checks above cover them.
|
|
15564
|
+
if (isRoot) {
|
|
15565
|
+
const dropped = Object.entries(otherProps)
|
|
15566
|
+
.filter(([, value]) => value !== undefined && value !== null && value !== false)
|
|
15567
|
+
.map(([key]) => key);
|
|
15568
|
+
if (className) {
|
|
15569
|
+
dropped.unshift('className');
|
|
15570
|
+
}
|
|
15571
|
+
if (dropped.length > 0) {
|
|
15572
|
+
warnOnce('Theme:root-dropped-props', `[bestax-bulma] <Theme isRoot>: a root Theme renders no wrapper ` +
|
|
15573
|
+
`element, so ${dropped.join(', ')} ` +
|
|
15574
|
+
`${dropped.length === 1 ? 'has' : 'have'} nothing to apply to. ` +
|
|
15575
|
+
'Put helper props and classes on an element inside the Theme ' +
|
|
15576
|
+
'instead.');
|
|
15577
|
+
}
|
|
15578
|
+
}
|
|
15527
15579
|
// Use Bulma classes for styling (only when not isRoot). Only a helper value
|
|
15528
15580
|
// of `radius` reaches the helper; a legacy string went to the variable.
|
|
15529
15581
|
const { bulmaHelperClasses, rest } = useBulmaClasses({
|