@allxsmith/bestax-bulma 5.18.1 → 5.18.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 +137 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +137 -35
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/Avatar.d.ts +3 -0
- package/dist/types/components/Dropdown.d.ts +6 -1
- package/dist/types/components/Menu.d.ts +6 -1
- package/dist/types/components/Toast.d.ts +15 -4
- package/dist/types/elements/Notification.d.ts +16 -4
- package/dist/types/helpers/buttonType.d.ts +19 -0
- package/dist/types/helpers/positionStacks.d.ts +33 -0
- package/dist/types-cjs/components/Avatar.d.ts +3 -0
- package/dist/types-cjs/components/Dropdown.d.ts +6 -1
- package/dist/types-cjs/components/Menu.d.ts +6 -1
- package/dist/types-cjs/components/Toast.d.ts +15 -4
- package/dist/types-cjs/elements/Notification.d.ts +16 -4
- package/dist/types-cjs/helpers/buttonType.d.ts +19 -0
- package/dist/types-cjs/helpers/positionStacks.d.ts +33 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1235,6 +1235,27 @@ const ColumnsComponent = ({ className, textColor, color: _fieldColor, bgColor, i
|
|
|
1235
1235
|
};
|
|
1236
1236
|
const Columns = withSubComponents(ColumnsComponent, { Column }, 'Columns');
|
|
1237
1237
|
|
|
1238
|
+
/**
|
|
1239
|
+
* The `type` to render on a `<button>` a component defaults to `button`: the
|
|
1240
|
+
* caller's own value when it is `button`, `submit` or `reset`, and `button`
|
|
1241
|
+
* otherwise.
|
|
1242
|
+
*
|
|
1243
|
+
* A missing `type` is not the only way a button ends up submitting the form
|
|
1244
|
+
* around it. HTML reads an invalid value, such as the anchor's MIME-type
|
|
1245
|
+
* `type="text/html"`, as submit too, and a props spread carrying
|
|
1246
|
+
* `type: undefined` removes the attribute outright. Both can arrive through a
|
|
1247
|
+
* spread or an untyped caller the component's own types never see, so this
|
|
1248
|
+
* checks the value rather than trusting where it came from.
|
|
1249
|
+
*
|
|
1250
|
+
* Call it AFTER the forwarded props are spread and pass it the forwarded
|
|
1251
|
+
* `type`, so its result is the attribute that renders.
|
|
1252
|
+
*/
|
|
1253
|
+
function buttonType(given) {
|
|
1254
|
+
return given === 'submit' || given === 'reset' || given === 'button'
|
|
1255
|
+
? given
|
|
1256
|
+
: 'button';
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1238
1259
|
/**
|
|
1239
1260
|
* Whether an `as` target is a custom element rather than a built-in tag.
|
|
1240
1261
|
*
|
|
@@ -1532,7 +1553,7 @@ const Avatar = forwardRef(function Avatar(avatarProps, ref) {
|
|
|
1532
1553
|
// The decorative opt-out never applies to an interactive avatar — a link or
|
|
1533
1554
|
// button must always expose an accessible name.
|
|
1534
1555
|
const isDecorative = alt === '' && !isInteractive;
|
|
1535
|
-
const
|
|
1556
|
+
const a11yDefaults = showImage
|
|
1536
1557
|
? isInteractive && !accessibleName
|
|
1537
1558
|
? // The img alt normally names the control; with no alt/name (an API
|
|
1538
1559
|
// returning only a photo URL) the link/button would be nameless.
|
|
@@ -1544,10 +1565,18 @@ const Avatar = forwardRef(function Avatar(avatarProps, ref) {
|
|
|
1544
1565
|
...(isInteractive ? {} : { role: 'img' }),
|
|
1545
1566
|
'aria-label': accessibleName || name || 'Avatar',
|
|
1546
1567
|
};
|
|
1547
|
-
//
|
|
1548
|
-
//
|
|
1549
|
-
|
|
1550
|
-
|
|
1568
|
+
// Each default yields to a value the caller passed, and is applied after
|
|
1569
|
+
// `rest` reading through it rather than spread before it. React treats an
|
|
1570
|
+
// `undefined` attribute as "remove it", and a spread carrying the key with no
|
|
1571
|
+
// value is how that arrives, so a default spread first was erased by it: an
|
|
1572
|
+
// `aria-label: undefined` left a button avatar nameless, and `role` and
|
|
1573
|
+
// `aria-hidden` went the same way. The button `type` below has the same
|
|
1574
|
+
// shape (#690).
|
|
1575
|
+
const a11yProps = Object.fromEntries(Object.entries(a11yDefaults).map(([key, fallback]) => [
|
|
1576
|
+
key,
|
|
1577
|
+
rest[key] ?? fallback,
|
|
1578
|
+
]));
|
|
1579
|
+
return (jsxs(Tag, { ref: ref, className: combinedClasses, style: { ...sizeStyle, ...style }, ...linkProps, ...rest, ...a11yProps, ...(Tag === 'button' ? { type: buttonType(rest.type) } : {}), children: [showImage && (jsx("img", { ...imageProps, ref: imgRef, src: src, alt: accessibleName ?? '', onError: e => {
|
|
1551
1580
|
imageProps?.onError?.(e);
|
|
1552
1581
|
setErroredSrc(src);
|
|
1553
1582
|
} }, src)), showInitials && (jsx("span", { className: initialsClass, children: resolvedInitials })), showIcon && icon, showDefaultIcon && jsx(DefaultAvatarIcon, {})] }));
|
|
@@ -2047,7 +2076,6 @@ const CardFooterItem = ({ as = 'span', className, children, color, bgColor, text
|
|
|
2047
2076
|
}
|
|
2048
2077
|
const forwarded = omitAttrs(rest, STRIP_FROM_NON_ANCHOR$1);
|
|
2049
2078
|
if (as === 'button') {
|
|
2050
|
-
const forwardedType = forwarded.type;
|
|
2051
2079
|
return (jsx("button", { className: itemClasses, ...forwarded,
|
|
2052
2080
|
// A footer item button must not submit an enclosing form by default —
|
|
2053
2081
|
// `<button>` defaults to `type="submit"`, and a Save/Cancel action row
|
|
@@ -2057,13 +2085,9 @@ const CardFooterItem = ({ as = 'span', className, children, color, bgColor, text
|
|
|
2057
2085
|
// typed here as the `<a>` MIME string (`STRIP_FROM_NON_ANCHOR` above
|
|
2058
2086
|
// says why it is not withheld), so `as="button" type="text/html"`
|
|
2059
2087
|
// compiles, and HTML's INVALID-value default for a button's `type` is
|
|
2060
|
-
// submit too.
|
|
2061
|
-
//
|
|
2062
|
-
type:
|
|
2063
|
-
forwardedType === 'reset' ||
|
|
2064
|
-
forwardedType === 'button'
|
|
2065
|
-
? forwardedType
|
|
2066
|
-
: 'button', children: children }));
|
|
2088
|
+
// submit too. `buttonType` keeps `button`, `submit` and `reset` and
|
|
2089
|
+
// turns anything else into `button`.
|
|
2090
|
+
type: buttonType(forwarded.type), children: children }));
|
|
2067
2091
|
}
|
|
2068
2092
|
return (jsx("span", { className: itemClasses, ...omitAttrs(forwarded, STRIP_FROM_NON_BUTTON), children: children }));
|
|
2069
2093
|
};
|
|
@@ -2400,9 +2424,7 @@ const DropdownItem = ((itemProps) => {
|
|
|
2400
2424
|
// carrying `role: undefined` would otherwise erase the default, and an
|
|
2401
2425
|
// item with no role drops out of the menu and its arrow-key order.
|
|
2402
2426
|
role: forwarded.role ?? 'menuitem', ...(Component === 'button'
|
|
2403
|
-
? {
|
|
2404
|
-
type: forwarded.type ?? 'button',
|
|
2405
|
-
}
|
|
2427
|
+
? { type: buttonType(forwarded.type) }
|
|
2406
2428
|
: {}), children: children }));
|
|
2407
2429
|
});
|
|
2408
2430
|
/**
|
|
@@ -2511,7 +2533,9 @@ const MenuItem = forwardRef(function MenuItem(itemProps, ref) {
|
|
|
2511
2533
|
labelChildren.push(child);
|
|
2512
2534
|
}
|
|
2513
2535
|
});
|
|
2514
|
-
return (jsxs("li", { className: className, "data-testid": testId, style: style, id: id, title: title, role: role, tabIndex: tabIndex, children: [jsx(Component, { ref: ref, className: itemClass || undefined, ...linkProps,
|
|
2536
|
+
return (jsxs("li", { className: className, "data-testid": testId, style: style, id: id, title: title, role: role, tabIndex: tabIndex, children: [jsx(Component, { ref: ref, className: itemClass || undefined, ...linkProps, ...(Component === 'button'
|
|
2537
|
+
? { type: buttonType(linkProps.type) }
|
|
2538
|
+
: {}), children: labelChildren }), nestedMenuLists] }));
|
|
2515
2539
|
});
|
|
2516
2540
|
MenuItem.displayName = 'MenuItem';
|
|
2517
2541
|
// Attach static subcomponents
|
|
@@ -4711,6 +4735,48 @@ const Sidebar = withSubComponents(SidebarComponent, {
|
|
|
4711
4735
|
Footer: SidebarFooter,
|
|
4712
4736
|
}, 'Sidebar');
|
|
4713
4737
|
|
|
4738
|
+
/**
|
|
4739
|
+
* Splits the items a container shows into one stack per position in use. An
|
|
4740
|
+
* item goes to its own position when it has one and to the container's
|
|
4741
|
+
* otherwise. A position with no items gets no stack.
|
|
4742
|
+
*
|
|
4743
|
+
* Stacks come back in `order`, so their order in the page follows the screen
|
|
4744
|
+
* rather than which position happened to be used first, and a stack keeps its
|
|
4745
|
+
* place while the others come and go. A position missing from `order` sorts
|
|
4746
|
+
* after the known ones.
|
|
4747
|
+
*
|
|
4748
|
+
* @function groupIntoPositionStacks
|
|
4749
|
+
* @param items - The items the container shows, in the order they were shown.
|
|
4750
|
+
* @param positionOf - Reads an item's own position, if it has one.
|
|
4751
|
+
* @param containerPosition - Where an item without a position of its own goes.
|
|
4752
|
+
* @param order - Every known position, in the order stacks should render.
|
|
4753
|
+
* @returns One stack per position in use.
|
|
4754
|
+
*/
|
|
4755
|
+
function groupIntoPositionStacks(items, positionOf, containerPosition, order) {
|
|
4756
|
+
const byPosition = new Map();
|
|
4757
|
+
for (const item of items) {
|
|
4758
|
+
const position = positionOf(item) ?? containerPosition;
|
|
4759
|
+
const stack = byPosition.get(position);
|
|
4760
|
+
if (stack) {
|
|
4761
|
+
stack.push(item);
|
|
4762
|
+
}
|
|
4763
|
+
else {
|
|
4764
|
+
byPosition.set(position, [item]);
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
const rank = (position) => {
|
|
4768
|
+
const index = order.indexOf(position);
|
|
4769
|
+
return index === -1 ? order.length : index;
|
|
4770
|
+
};
|
|
4771
|
+
// Array.prototype.sort is stable, so unknown positions keep the order they
|
|
4772
|
+
// were first used in.
|
|
4773
|
+
return Array.from(byPosition, ([position, stackItems]) => ({
|
|
4774
|
+
key: position === containerPosition ? 'container' : `at-${position}`,
|
|
4775
|
+
position,
|
|
4776
|
+
items: stackItems,
|
|
4777
|
+
})).sort((a, b) => rank(a.position) - rank(b.position));
|
|
4778
|
+
}
|
|
4779
|
+
|
|
4714
4780
|
/**
|
|
4715
4781
|
* The `Toast` component provides brief notification messages with optional action and cancel buttons.
|
|
4716
4782
|
*
|
|
@@ -4987,25 +5053,38 @@ const toast = {
|
|
|
4987
5053
|
return () => toastListeners.delete(listener);
|
|
4988
5054
|
},
|
|
4989
5055
|
};
|
|
5056
|
+
// The order ToastContainer renders its stacks in: across the top of the
|
|
5057
|
+
// screen, then across the bottom.
|
|
5058
|
+
const toastStackOrder = [
|
|
5059
|
+
'top-left',
|
|
5060
|
+
'top-center',
|
|
5061
|
+
'top-right',
|
|
5062
|
+
'bottom-left',
|
|
5063
|
+
'bottom-center',
|
|
5064
|
+
'bottom-right',
|
|
5065
|
+
];
|
|
4990
5066
|
/**
|
|
4991
5067
|
* Container component for rendering programmatic toasts.
|
|
4992
|
-
* Place once at your app root to enable the toast API.
|
|
5068
|
+
* Place once at your app root to enable the toast API. A toast shown with a
|
|
5069
|
+
* `position` appears there, and one shown without goes to the container's
|
|
5070
|
+
* `position`.
|
|
4993
5071
|
*
|
|
4994
5072
|
* @function
|
|
4995
5073
|
* @param {{ position?: ToastPosition }} props - Container props.
|
|
4996
5074
|
* @returns {JSX.Element | null} The rendered toast container, or null if empty.
|
|
4997
5075
|
*/
|
|
4998
|
-
const ToastContainer = ({ position = 'top-right'
|
|
5076
|
+
const ToastContainer = ({ position = 'top-right' }) => {
|
|
4999
5077
|
// Starts from the toasts already showing instead of an empty list, then
|
|
5000
5078
|
// follows changes.
|
|
5001
5079
|
const toastList = useSyncExternalStore(toast.subscribe, getVisibleToasts, getServerToasts);
|
|
5002
5080
|
if (typeof document === 'undefined' || toastList.length === 0) {
|
|
5003
5081
|
return null;
|
|
5004
5082
|
}
|
|
5005
|
-
|
|
5083
|
+
const stacks = groupIntoPositionStacks(toastList, t => t.props.position, position, toastStackOrder);
|
|
5084
|
+
return createPortal(stacks.map(stack => (jsx("div", { className: `toast-container is-${stack.position}`, children: stack.items.map(t => {
|
|
5006
5085
|
const { queue: _queue, ...toastProps } = t.props;
|
|
5007
|
-
return (jsx(Toast, { ...toastProps, position: position, onClose: () => toast.close(t.id) }, t.id));
|
|
5008
|
-
}) }), document.body);
|
|
5086
|
+
return (jsx(Toast, { ...toastProps, position: stack.position, onClose: () => toast.close(t.id) }, t.id));
|
|
5087
|
+
}) }, stack.key))), document.body);
|
|
5009
5088
|
};
|
|
5010
5089
|
|
|
5011
5090
|
/**
|
|
@@ -6449,25 +6528,28 @@ const NotificationItem = ({ instance, onClose }) => {
|
|
|
6449
6528
|
}, [pauseOnHover]);
|
|
6450
6529
|
return (jsx(Notification, { color: color, isLight: isLight, hasDelete: hasDelete, onDelete: handleClose, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: { pointerEvents: 'auto' }, children: urgent ? (jsx("span", { role: "alert", "aria-live": "assertive", children: message })) : (jsx("span", { role: "status", "aria-live": "polite", children: message })) }));
|
|
6451
6530
|
};
|
|
6531
|
+
// The order NotificationContainer renders its stacks in: across the top of the
|
|
6532
|
+
// screen, then across the bottom.
|
|
6533
|
+
const notificationStackOrder = [
|
|
6534
|
+
'top-left',
|
|
6535
|
+
'top',
|
|
6536
|
+
'top-right',
|
|
6537
|
+
'bottom-left',
|
|
6538
|
+
'bottom',
|
|
6539
|
+
'bottom-right',
|
|
6540
|
+
];
|
|
6452
6541
|
/**
|
|
6453
|
-
*
|
|
6454
|
-
* Place once at your app root to enable the notification API.
|
|
6542
|
+
* Inline style that fixes a stack of notifications to its place on the screen.
|
|
6455
6543
|
*
|
|
6456
6544
|
* @function
|
|
6457
|
-
* @param {
|
|
6458
|
-
* @returns {
|
|
6545
|
+
* @param {NotificationPosition} position - Where the stack sits.
|
|
6546
|
+
* @returns {React.CSSProperties} The stack's style.
|
|
6459
6547
|
*/
|
|
6460
|
-
const
|
|
6461
|
-
// Starts from the notifications already showing instead of an empty list,
|
|
6462
|
-
// then follows changes.
|
|
6463
|
-
const items = useSyncExternalStore(notification.subscribe, getVisibleNotifications, getServerNotifications);
|
|
6464
|
-
if (typeof document === 'undefined' || items.length === 0) {
|
|
6465
|
-
return null;
|
|
6466
|
-
}
|
|
6548
|
+
const notificationStackStyle = (position) => {
|
|
6467
6549
|
const isBottom = position.startsWith('bottom');
|
|
6468
6550
|
const isCenter = position === 'top' || position === 'bottom';
|
|
6469
6551
|
const isRight = position.endsWith('right');
|
|
6470
|
-
|
|
6552
|
+
return {
|
|
6471
6553
|
position: 'fixed',
|
|
6472
6554
|
zIndex: 100,
|
|
6473
6555
|
display: 'flex',
|
|
@@ -6483,7 +6565,27 @@ const NotificationContainer = ({ position = 'top-right' }) => {
|
|
|
6483
6565
|
? { right: 0, alignItems: 'flex-end' }
|
|
6484
6566
|
: { left: 0, alignItems: 'flex-start' }),
|
|
6485
6567
|
};
|
|
6486
|
-
|
|
6568
|
+
};
|
|
6569
|
+
/**
|
|
6570
|
+
* Container component for rendering programmatic notifications.
|
|
6571
|
+
* Place once at your app root to enable the notification API. A notification
|
|
6572
|
+
* shown with a `position` appears there, and one shown without goes to the
|
|
6573
|
+
* container's `position`, so the container renders a stack for each position
|
|
6574
|
+
* in use.
|
|
6575
|
+
*
|
|
6576
|
+
* @function
|
|
6577
|
+
* @param {{ position?: NotificationPosition }} props - Container props.
|
|
6578
|
+
* @returns {JSX.Element | null} The rendered notification container, or null if empty.
|
|
6579
|
+
*/
|
|
6580
|
+
const NotificationContainer = ({ position = 'top-right' }) => {
|
|
6581
|
+
// Starts from the notifications already showing instead of an empty list,
|
|
6582
|
+
// then follows changes.
|
|
6583
|
+
const items = useSyncExternalStore(notification.subscribe, getVisibleNotifications, getServerNotifications);
|
|
6584
|
+
if (typeof document === 'undefined' || items.length === 0) {
|
|
6585
|
+
return null;
|
|
6586
|
+
}
|
|
6587
|
+
const stacks = groupIntoPositionStacks(items, item => item.options.position, position, notificationStackOrder);
|
|
6588
|
+
return createPortal(stacks.map(stack => (jsx("div", { style: notificationStackStyle(stack.position), children: stack.items.map(item => (jsx(NotificationItem, { instance: item, onClose: notification.close }, item.id))) }, stack.key))), document.body);
|
|
6487
6589
|
};
|
|
6488
6590
|
|
|
6489
6591
|
/**
|