@dynamic-framework/ui-react 2.10.0 → 2.11.0
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/DPortalStack-6zJm6JoD.js +14 -0
- package/dist/DPortalStack-6zJm6JoD.js.map +1 -0
- package/dist/DPortalStack-D1-GGU4C.js +12 -0
- package/dist/DPortalStack-D1-GGU4C.js.map +1 -0
- package/dist/api.json +7429 -0
- package/dist/css/dynamic-ui.css +95 -26
- package/dist/css/dynamic-ui.min.css +2 -2
- package/dist/esm/components/DAlert/DAlert.js +2 -2
- package/dist/esm/components/DAlert/DAlert.js.map +1 -1
- package/dist/esm/components/DButtonIcon/DButtonIcon.js +6 -3
- package/dist/esm/components/DButtonIcon/DButtonIcon.js.map +1 -1
- package/dist/esm/components/DDataStateWrapper/DDataStateWrapper.js +10 -3
- package/dist/esm/components/DDataStateWrapper/DDataStateWrapper.js.map +1 -1
- package/dist/esm/components/DErrorBoundary/DErrorBoundary.js +3 -3
- package/dist/esm/components/DErrorBoundary/DErrorBoundary.js.map +1 -1
- package/dist/esm/components/DErrorBoundary/components/DefaultErrorBoundary.js +2 -2
- package/dist/esm/components/DErrorBoundary/components/DefaultErrorBoundary.js.map +1 -1
- package/dist/esm/components/DInput/DInput.js +15 -3
- package/dist/esm/components/DInput/DInput.js.map +1 -1
- package/dist/esm/components/DInputCheck/DInputCheck.js +45 -8
- package/dist/esm/components/DInputCheck/DInputCheck.js.map +1 -1
- package/dist/esm/components/DInputCounter/DInputCounter.js +78 -20
- package/dist/esm/components/DInputCounter/DInputCounter.js.map +1 -1
- package/dist/esm/components/DInputCurrency/DInputCurrency.js +8 -3
- package/dist/esm/components/DInputCurrency/DInputCurrency.js.map +1 -1
- package/dist/esm/components/DInputPhone/DInputPhone.js +14 -2
- package/dist/esm/components/DInputPhone/DInputPhone.js.map +1 -1
- package/dist/esm/components/DInputPin/DInputPin.js +3 -1
- package/dist/esm/components/DInputPin/DInputPin.js.map +1 -1
- package/dist/esm/components/DInputRange/DInputRange.js +16 -2
- package/dist/esm/components/DInputRange/DInputRange.js.map +1 -1
- package/dist/esm/components/DInputSelect/DInputSelect.js +18 -4
- package/dist/esm/components/DInputSelect/DInputSelect.js.map +1 -1
- package/dist/esm/components/DInputSwitch/DInputSwitch.js +20 -9
- package/dist/esm/components/DInputSwitch/DInputSwitch.js.map +1 -1
- package/dist/esm/components/DListGroup/DListGroup.js +10 -2
- package/dist/esm/components/DListGroup/DListGroup.js.map +1 -1
- package/dist/esm/components/DListGroup/ListGroupContext.js +11 -0
- package/dist/esm/components/DListGroup/ListGroupContext.js.map +1 -0
- package/dist/esm/components/DListGroup/components/DListGroupItem.js +34 -16
- package/dist/esm/components/DListGroup/components/DListGroupItem.js.map +1 -1
- package/dist/esm/components/DListGroup/components/warnInvalidListMarkup.js +30 -0
- package/dist/esm/components/DListGroup/components/warnInvalidListMarkup.js.map +1 -0
- package/dist/esm/components/DPasswordStrengthMeter/DPasswordStrengthMeter.js +2 -2
- package/dist/esm/components/DPasswordStrengthMeter/DPasswordStrengthMeter.js.map +1 -1
- package/dist/esm/components/DProgress/DProgress.js +9 -3
- package/dist/esm/components/DProgress/DProgress.js.map +1 -1
- package/dist/esm/components/DSelect/DSelect.js +31 -3
- package/dist/esm/components/DSelect/DSelect.js.map +1 -1
- package/dist/esm/components/DSelect/createAriaGuidance.js +57 -0
- package/dist/esm/components/DSelect/createAriaGuidance.js.map +1 -0
- package/dist/esm/components/DTabs/DTabs.js +29 -40
- package/dist/esm/components/DTabs/DTabs.js.map +1 -1
- package/dist/esm/components/DTabs/TabContext.js +3 -2
- package/dist/esm/components/DTabs/TabContext.js.map +1 -1
- package/dist/esm/components/DTabs/components/DTabContent.js +2 -2
- package/dist/esm/components/DTabs/components/DTabContent.js.map +1 -1
- package/dist/esm/components/DTabs/components/DTabsProvider.js +22 -0
- package/dist/esm/components/DTabs/components/DTabsProvider.js.map +1 -0
- package/dist/esm/components/DTabs/index.js +1 -0
- package/dist/esm/components/DTabs/index.js.map +1 -1
- package/dist/esm/components/DToast/DToast.js +7 -2
- package/dist/esm/components/DToast/DToast.js.map +1 -1
- package/dist/esm/components/DToastContainer/useDToast.js +5 -5
- package/dist/esm/components/DToastContainer/useDToast.js.map +1 -1
- package/dist/esm/components/internal/DFormLabel.js +46 -0
- package/dist/esm/components/internal/DFormLabel.js.map +1 -0
- package/dist/esm/contexts/DPortalContext.js +43 -8
- package/dist/esm/contexts/DPortalContext.js.map +1 -1
- package/dist/esm/contexts/portal/DPortalStack.js +12 -0
- package/dist/esm/contexts/portal/DPortalStack.js.map +1 -0
- package/dist/esm/hooks/useControlledState.js +51 -0
- package/dist/esm/hooks/useControlledState.js.map +1 -0
- package/dist/esm/hooks/useInputCurrency.js +73 -19
- package/dist/esm/hooks/useInputCurrency.js.map +1 -1
- package/dist/esm/hooks/useMediaBreakpointUp.js +42 -3
- package/dist/esm/hooks/useMediaBreakpointUp.js.map +1 -1
- package/dist/esm/hooks/useResponsiveProp.js +13 -2
- package/dist/esm/hooks/useResponsiveProp.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/hasLabelContent.js +48 -0
- package/dist/esm/utils/hasLabelContent.js.map +1 -0
- package/dist/esm/utils/isTextLabel.js +23 -0
- package/dist/esm/utils/isTextLabel.js.map +1 -0
- package/dist/esm/utils/labelClickGuard.js +61 -0
- package/dist/esm/utils/labelClickGuard.js.map +1 -0
- package/dist/esm/utils/warnLabelUsage.js +57 -0
- package/dist/esm/utils/warnLabelUsage.js.map +1 -0
- package/dist/icons-core.json +1 -1
- package/dist/index.esm.js +865 -163
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +864 -161
- package/dist/index.js.map +1 -1
- package/dist/types/components/DAlert/DAlert.d.ts +16 -2
- package/dist/types/components/DButtonIcon/DButtonIcon.d.ts +9 -1
- package/dist/types/components/DDataStateWrapper/DDataStateWrapper.d.ts +29 -4
- package/dist/types/components/DDataStateWrapper/index.d.ts +1 -1
- package/dist/types/components/DErrorBoundary/DErrorBoundary.d.ts +6 -1
- package/dist/types/components/DErrorBoundary/components/DefaultErrorBoundary.d.ts +3 -1
- package/dist/types/components/DInput/DInput.d.ts +11 -2
- package/dist/types/components/DInputCheck/DInputCheck.d.ts +28 -3
- package/dist/types/components/DInputCounter/DInputCounter.d.ts +15 -3
- package/dist/types/components/DInputCurrency/DInputCurrency.d.ts +10 -3
- package/dist/types/components/DInputPhone/DInputPhone.d.ts +11 -2
- package/dist/types/components/DInputPin/DInputPin.d.ts +12 -2
- package/dist/types/components/DInputRange/DInputRange.d.ts +15 -2
- package/dist/types/components/DInputSelect/DInputSelect.d.ts +18 -3
- package/dist/types/components/DInputSwitch/DInputSwitch.d.ts +28 -3
- package/dist/types/components/DListGroup/DListGroup.d.ts +12 -1
- package/dist/types/components/DListGroup/ListGroupContext.d.ts +8 -0
- package/dist/types/components/DListGroup/components/DListGroupItem.d.ts +6 -1
- package/dist/types/components/DListGroup/components/warnInvalidListMarkup.d.ts +13 -0
- package/dist/types/components/DPasswordStrengthMeter/DPasswordStrengthMeter.d.ts +18 -3
- package/dist/types/components/DProgress/DProgress.d.ts +13 -1
- package/dist/types/components/DSelect/DSelect.d.ts +23 -3
- package/dist/types/components/DSelect/createAriaGuidance.d.ts +21 -0
- package/dist/types/components/DTabs/DTabs.d.ts +13 -2
- package/dist/types/components/DTabs/TabContext.d.ts +5 -0
- package/dist/types/components/DTabs/components/DTabsProvider.d.ts +11 -0
- package/dist/types/components/DTabs/index.d.ts +1 -0
- package/dist/types/components/DToast/DToast.d.ts +10 -3
- package/dist/types/components/DToastContainer/useDToast.d.ts +8 -1
- package/dist/types/components/index.d.ts +2 -2
- package/dist/types/components/interface.d.ts +7 -0
- package/dist/types/components/internal/DFormLabel.d.ts +30 -0
- package/dist/types/contexts/portal/DPortalStack.d.ts +13 -0
- package/dist/types/hooks/useControlledState.d.ts +17 -0
- package/dist/types/hooks/useInputCurrency.d.ts +26 -1
- package/dist/types/hooks/useMediaBreakpointUp.d.ts +10 -0
- package/dist/types/utils/hasLabelContent.d.ts +30 -0
- package/dist/types/utils/isTextLabel.d.ts +17 -0
- package/dist/types/utils/labelClickGuard.d.ts +20 -0
- package/dist/types/utils/warnLabelUsage.d.ts +43 -0
- package/package.json +8 -3
- package/src/style/abstracts/variables/_body.scss +2 -2
- package/src/style/abstracts/variables/_chips.scss +2 -0
- package/src/style/abstracts/variables/_colors.scss +2 -2
- package/src/style/base/_buttons.scss +4 -1
- package/src/style/base/_input-group.scss +5 -2
- package/src/style/base/_list-group.scss +55 -0
- package/src/style/components/_d-chip.scss +7 -2
- package/src/style/components/_d-tabs.scss +3 -0
- package/src/style/helpers/_color-bg.scss +5 -0
- package/src/style/root/_root.scss +9 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PropsWithChildren } from 'react';
|
|
2
2
|
import DTabContent from './components/DTabContent';
|
|
3
|
+
import DTabsProvider from './components/DTabsProvider';
|
|
3
4
|
import type { BaseProps } from '../interface';
|
|
4
5
|
export type DTabOption = {
|
|
5
6
|
label: string | React.ReactNode;
|
|
@@ -9,16 +10,26 @@ export type DTabOption = {
|
|
|
9
10
|
export type TabVariant = 'tabs' | 'pills' | 'underline' | 'toggle-button-group';
|
|
10
11
|
type Props = BaseProps & PropsWithChildren<{
|
|
11
12
|
classNameTab?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Class for the panels container. It is only rendered when `DTabs` has
|
|
15
|
+
* children, so a tab bar used as pure navigation leaves no empty node.
|
|
16
|
+
*/
|
|
17
|
+
classNameContent?: string;
|
|
12
18
|
onChange?: (option: DTabOption) => void;
|
|
13
19
|
options: Array<DTabOption>;
|
|
14
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Ignored inside `DTabs.Provider`, which owns the selection. Without it, the
|
|
22
|
+
* first enabled tab is selected when omitted.
|
|
23
|
+
*/
|
|
24
|
+
defaultSelected?: string;
|
|
15
25
|
vertical?: boolean;
|
|
16
26
|
variant?: TabVariant;
|
|
17
27
|
ariaLabel?: string;
|
|
18
28
|
ariaLabelledBy?: string;
|
|
19
29
|
}>;
|
|
20
|
-
declare function DTabs({ children, defaultSelected, onChange, options, className, classNameTab, style, vertical, variant, dataAttributes, ariaLabel, ariaLabelledBy, }: Props): import("react").JSX.Element;
|
|
30
|
+
declare function DTabs({ children, defaultSelected, onChange, options, className, classNameTab, classNameContent, style, vertical, variant, dataAttributes, ariaLabel, ariaLabelledBy, }: Props): import("react").JSX.Element;
|
|
21
31
|
declare const _default: typeof DTabs & {
|
|
22
32
|
Tab: typeof DTabContent;
|
|
33
|
+
Provider: typeof DTabsProvider;
|
|
23
34
|
};
|
|
24
35
|
export default _default;
|
|
@@ -4,5 +4,10 @@ type TabContextState = {
|
|
|
4
4
|
isSelected: (tab: DTabOption['tab']) => boolean;
|
|
5
5
|
};
|
|
6
6
|
declare const TabContext: import("react").Context<TabContextState | undefined>;
|
|
7
|
+
type TabsState = {
|
|
8
|
+
selected: string;
|
|
9
|
+
setSelected: (tab: string) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare const TabsStateContext: import("react").Context<TabsState | undefined>;
|
|
7
12
|
export declare function useTabContext(): TabContextState;
|
|
8
13
|
export default TabContext;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
|
2
|
+
type Props = PropsWithChildren<{
|
|
3
|
+
defaultSelected: string;
|
|
4
|
+
}>;
|
|
5
|
+
/**
|
|
6
|
+
* Owns the selected tab so the tab bar (`DTabs`) and its panels (`DTabs.Tab`)
|
|
7
|
+
* can live anywhere inside it, e.g. the bar in a header and the panels in
|
|
8
|
+
* another column.
|
|
9
|
+
*/
|
|
10
|
+
export default function DTabsProvider({ defaultSelected, children, }: Props): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import DTabs from './DTabs';
|
|
2
2
|
export type { DTabOption } from './DTabs';
|
|
3
3
|
export { default as DTabContent } from './components/DTabContent';
|
|
4
|
+
export { default as DTabsProvider } from './components/DTabsProvider';
|
|
4
5
|
export { useTabContext } from './TabContext';
|
|
5
6
|
export default DTabs;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
2
|
import DToastHeader from './components/DToastHeader';
|
|
3
3
|
import DToastBody from './components/DToastBody';
|
|
4
|
-
import { BaseProps } from '../interface';
|
|
5
|
-
type Props = PropsWithChildren<BaseProps
|
|
6
|
-
|
|
4
|
+
import { BaseProps, LiveRegionRole } from '../interface';
|
|
5
|
+
type Props = PropsWithChildren<BaseProps & {
|
|
6
|
+
/**
|
|
7
|
+
* `alert` (default) interrupts the screen reader, for critical errors.
|
|
8
|
+
* `status` announces without interrupting, for confirmations and other
|
|
9
|
+
* non-critical messages. `none` renders no live region.
|
|
10
|
+
*/
|
|
11
|
+
role?: LiveRegionRole;
|
|
12
|
+
}>;
|
|
13
|
+
declare function DToast({ children, role, className, style, dataAttributes, }: Props): import("react").JSX.Element;
|
|
7
14
|
declare const _default: typeof DToast & {
|
|
8
15
|
Header: typeof DToastHeader;
|
|
9
16
|
Body: typeof DToastBody;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Renderable, Toast, ToastPosition, ValueFunction } from 'react-hot-toast';
|
|
2
|
-
import { ComponentStateColor } from '../interface';
|
|
2
|
+
import { ComponentStateColor, LiveRegionRole } from '../interface';
|
|
3
3
|
/**
|
|
4
4
|
* Data used to render the default DToast component via `useDToast`.
|
|
5
5
|
* When `description` is provided, the toast renders with a header and body layout.
|
|
@@ -19,6 +19,13 @@ export type ToastData = {
|
|
|
19
19
|
closeIcon?: string;
|
|
20
20
|
/** Applies the `toast-{color}` CSS modifier class. */
|
|
21
21
|
color?: ComponentStateColor;
|
|
22
|
+
/**
|
|
23
|
+
* Live region role of the toast. Defaults to `alert`; use `status` for
|
|
24
|
+
* confirmations so the screen reader doesn't interrupt the user.
|
|
25
|
+
*/
|
|
26
|
+
role?: LiveRegionRole;
|
|
27
|
+
/** Accessible name of the close button. Defaults to `"Close"`. */
|
|
28
|
+
closeAriaLabel?: string;
|
|
22
29
|
};
|
|
23
30
|
/** Options forwarded to react-hot-toast for a single toast instance. */
|
|
24
31
|
export interface DToastOptions {
|
|
@@ -42,7 +42,7 @@ export { default as DStepperDesktop } from './DStepperDesktop';
|
|
|
42
42
|
export { default as DStepperMobile } from './DStepperMobile';
|
|
43
43
|
export { default as DTooltip } from './DTooltip';
|
|
44
44
|
export { default as DTimeline } from './DTimeline';
|
|
45
|
-
export { default as DTabs, useTabContext, DTabContent, } from './DTabs';
|
|
45
|
+
export { default as DTabs, useTabContext, DTabContent, DTabsProvider, } from './DTabs';
|
|
46
46
|
export type { DTabOption } from './DTabs';
|
|
47
47
|
export { default as DToast } from './DToast';
|
|
48
48
|
export { default as DToastContainer, useDToast, } from './DToastContainer';
|
|
@@ -54,6 +54,6 @@ export { default as DVoucher, useScreenshot, useScreenshotDownload, useScreensho
|
|
|
54
54
|
export { default as DOtp } from './DOtp';
|
|
55
55
|
export { default as DErrorBoundary, useErrorBoundary, type FallbackProps, getErrorMessage, } from './DErrorBoundary';
|
|
56
56
|
export { default as DDataStateWrapper, EmptyState, ErrorState, LoadingState, } from './DDataStateWrapper';
|
|
57
|
-
export type { DDataStateMessages } from './DDataStateWrapper';
|
|
57
|
+
export type { DDataStateMessages, DDataStateWrapperListProps, DDataStateWrapperSingleProps, } from './DDataStateWrapper';
|
|
58
58
|
export { default as DConfirmModalContainer } from './DConfirmModal/DConfirmModalContainer';
|
|
59
59
|
export type { ConfirmModalEntry, ConfirmModalStore } from './DConfirmModal/types';
|
|
@@ -11,6 +11,13 @@ export type NavegableProps = {
|
|
|
11
11
|
'aria-current'?: string;
|
|
12
12
|
};
|
|
13
13
|
export type ComponentSize = 'sm' | 'lg';
|
|
14
|
+
/**
|
|
15
|
+
* How a message is exposed to assistive technology: `alert` interrupts the
|
|
16
|
+
* screen reader (critical errors), `status` is announced without interrupting
|
|
17
|
+
* (non-critical dynamic messages) and `none` is not a live region (static
|
|
18
|
+
* content already on screen).
|
|
19
|
+
*/
|
|
20
|
+
export type LiveRegionRole = 'alert' | 'status' | 'none';
|
|
14
21
|
export type BreakpointSize = 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
|
15
22
|
export type AvatarSize = 'xs' | 'sm' | 'lg' | 'xl' | 'xxl';
|
|
16
23
|
export type DataAttributes = Record<`data-${string}`, string | number | undefined | null | boolean>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
type Props = {
|
|
3
|
+
htmlFor: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* The `<label>` every form control renders, with the click guard already wired.
|
|
9
|
+
*
|
|
10
|
+
* Internal: it exists so the guard — and the lint exception it needs — lives in
|
|
11
|
+
* one place instead of being repeated across every input component.
|
|
12
|
+
*
|
|
13
|
+
* The guard runs in the capture phase, not on bubble: a tooltip or modal
|
|
14
|
+
* trigger that calls `stopPropagation()` in its own handler — a common pattern —
|
|
15
|
+
* would otherwise keep the guard from ever running, and the browser would go on
|
|
16
|
+
* to activate the labelled control. Confirmed in Chromium, where the same
|
|
17
|
+
* trigger toggles the control with a bubble-phase guard and does not with this
|
|
18
|
+
* one. Capturing changes nothing else: `preventDefault` applies to the default
|
|
19
|
+
* action, which is evaluated after propagation either way.
|
|
20
|
+
*
|
|
21
|
+
* The `jsx-a11y` rules below assume a click handler is being used to make a
|
|
22
|
+
* non-interactive element interactive, which then owes the keyboard an
|
|
23
|
+
* equivalent. This handler does the opposite: it suppresses a pointer-only
|
|
24
|
+
* behaviour, the click a label forwards to its control, and adds no way to
|
|
25
|
+
* activate anything. Keyboard support for a nested trigger is the consumer's:
|
|
26
|
+
* `<a href>` carries its own, while a `span` with a role and a tabindex is
|
|
27
|
+
* focusable but inert until they handle Enter and Space themselves.
|
|
28
|
+
*/
|
|
29
|
+
export default function DFormLabel({ htmlFor, className, children }: Props): import("react").JSX.Element;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
type Props = {
|
|
3
|
+
stack: Array<{
|
|
4
|
+
name: string;
|
|
5
|
+
Component: FC<{
|
|
6
|
+
name: string;
|
|
7
|
+
payload: any;
|
|
8
|
+
}>;
|
|
9
|
+
payload: unknown;
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
export default function DPortalStack({ stack }: Props): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backs a value that the consumer may or may not drive, so a control works in
|
|
3
|
+
* both modes without a copy of the state drifting away from the props.
|
|
4
|
+
*
|
|
5
|
+
* A control counts as controlled only when the consumer passes the value *and*
|
|
6
|
+
* an `onChange` to push it back. The value on its own has always meant "start
|
|
7
|
+
* here" in this library — `<DInputCheck type="radio" checked />` inside a radio
|
|
8
|
+
* group, for one — so treating it as controlled would silently freeze those
|
|
9
|
+
* controls, and React emits no warning to say why: the components always attach
|
|
10
|
+
* their own `onChange` handler.
|
|
11
|
+
*
|
|
12
|
+
* @param value the value coming from props, or `undefined` when not passed.
|
|
13
|
+
* @param isControlled whether the consumer can drive the value back.
|
|
14
|
+
* @param initialValue what to start from when no value is passed.
|
|
15
|
+
* @returns the value to render, and a setter to call on every user change.
|
|
16
|
+
*/
|
|
17
|
+
export default function useControlledState<T>(value: T | undefined, isControlled: boolean, initialValue: T): [T, (next: T) => void];
|
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
import type { RefObject, ForwardedRef, FocusEvent } from 'react';
|
|
2
2
|
import type { Options } from 'currency.js';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* State and handlers for a currency input: a formatted string while the field
|
|
5
|
+
* is idle and the raw number while it is being edited.
|
|
6
|
+
*
|
|
7
|
+
* `minValue`/`maxValue` bound the value. With `clamp` (default `true`) an
|
|
8
|
+
* out-of-range value is brought into range whenever it is not being typed:
|
|
9
|
+
* on mount, when `value` or the bounds change, and on blur. Every time the
|
|
10
|
+
* clamp changes the value, `onChange` receives the clamped number, so the
|
|
11
|
+
* input and the consumer's state never disagree. While the field is focused
|
|
12
|
+
* the typed number is reported as is, so a partial entry is not rewritten.
|
|
13
|
+
*
|
|
14
|
+
* With `clamp: false` the value is never changed: the bounds only feed
|
|
15
|
+
* `isOverMax` / `isUnderMin`, so the consumer can show its own message (e.g.
|
|
16
|
+
* "You exceeded the limit") and keep the entered amount.
|
|
17
|
+
*
|
|
18
|
+
* Controlled usage follows the same contract as a native controlled input:
|
|
19
|
+
* reflect `onChange` into `value` in the same event (`setState` in the
|
|
20
|
+
* handler). The hook keeps showing `value` whenever it isn't being edited, so
|
|
21
|
+
* a consumer can reject a change by keeping `value` as it was. Deferring the
|
|
22
|
+
* update (a timer, awaiting a request) makes the hook see a stale `value` in
|
|
23
|
+
* between: the field can flash the previous amount and a clamp can be
|
|
24
|
+
* reported again when the deferred value arrives.
|
|
25
|
+
*/
|
|
26
|
+
export default function useInputCurrency(currencyOptions: Options, value?: number, onFocus?: (event: FocusEvent<HTMLInputElement>) => void, onChange?: (value?: number) => void, onBlur?: (event: FocusEvent<HTMLInputElement>) => void, ref?: ForwardedRef<HTMLInputElement>, minValue?: number, maxValue?: number, clamp?: boolean): {
|
|
4
27
|
inputRef: RefObject<HTMLInputElement | null>;
|
|
5
28
|
innerValue: string;
|
|
6
29
|
innerType: string;
|
|
30
|
+
isOverMax: boolean;
|
|
31
|
+
isUnderMin: boolean;
|
|
7
32
|
handleOnFocus: (event: FocusEvent<HTMLInputElement>) => void;
|
|
8
33
|
handleOnChange: (newValue?: string) => void;
|
|
9
34
|
handleOnBlur: (event: FocusEvent<HTMLInputElement>) => void;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import type { BreakpointProps } from '../contexts/DContext';
|
|
2
|
+
/** Clears the cached CSS breakpoints. Only meant for tests. */
|
|
3
|
+
export declare function resetCssBreakpointsCache(): void;
|
|
4
|
+
/**
|
|
5
|
+
* Pixel value of a breakpoint. `DContextProvider` reads them from the CSS and
|
|
6
|
+
* shares them through the context; outside of it (a tree without the
|
|
7
|
+
* provider, or its first render) they are read from the same CSS variables
|
|
8
|
+
* here, so responsive props resolve either way.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useBreakpointValue(breakpoint: keyof BreakpointProps): string;
|
|
1
11
|
export declare function useMediaBreakpointUpXs(useListener?: boolean): boolean;
|
|
2
12
|
export declare function useMediaBreakpointUpSm(useListener?: boolean): boolean;
|
|
3
13
|
export declare function useMediaBreakpointUpMd(useListener?: boolean): boolean;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Whether a `label` node has something to render.
|
|
4
|
+
*
|
|
5
|
+
* The render paths cannot test `label` for truthiness: since the prop widened
|
|
6
|
+
* to `ReactNode` it also accepts `0`, which React renders as the text "0" and
|
|
7
|
+
* which `isTextLabel` counts as a text label, yet which a truthiness check
|
|
8
|
+
* would drop — leaving the control visibly unlabelled.
|
|
9
|
+
*
|
|
10
|
+
* Absent (`undefined`, `null`), empty (`''`) and boolean labels render nothing,
|
|
11
|
+
* so they are the ones that stand for "no label". The empty string matters
|
|
12
|
+
* because it is the default several components fall back to.
|
|
13
|
+
*
|
|
14
|
+
* Arrays are inspected rather than taken at face value: `label={items.map(...)}`
|
|
15
|
+
* over an empty list yields `[]`, while a list of skipped entries yields
|
|
16
|
+
* `[false, null]`. Both render nothing, so treating them as content would leave
|
|
17
|
+
* an empty `<label>` on the page — and make the naming warning fire over a
|
|
18
|
+
* label that was never there.
|
|
19
|
+
*
|
|
20
|
+
* Only arrays, though, even though `ReactNode` admits any iterable. Reading a
|
|
21
|
+
* one-shot iterator — a generator — would exhaust it here, and the component
|
|
22
|
+
* goes on to render the same value, so the label would vanish precisely because
|
|
23
|
+
* we checked for it. An array can be walked as often as needed; anything else
|
|
24
|
+
* is taken on faith.
|
|
25
|
+
*
|
|
26
|
+
* Anything else — an element, a portal, a generator — counts as content: what
|
|
27
|
+
* it renders is only knowable by rendering it, and an element that draws
|
|
28
|
+
* nothing visible is the consumer's decision rather than an absent label.
|
|
29
|
+
*/
|
|
30
|
+
export default function hasLabelContent(label: ReactNode): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Narrows a `label` node to the plain-text case.
|
|
4
|
+
*
|
|
5
|
+
* `label` accepts any `ReactNode` so patterns like a terms-and-conditions link
|
|
6
|
+
* or an info trigger can live next to the field name. Anything that is not text
|
|
7
|
+
* cannot be forwarded to a string-only attribute (`aria-label`, `placeholder`)
|
|
8
|
+
* nor laid out by Bootstrap's `form-floating`, so those paths check this first.
|
|
9
|
+
*
|
|
10
|
+
* Numbers and bigints count as text: React renders them as their string form
|
|
11
|
+
* and so does `String()`, which is what the string-only attributes end up
|
|
12
|
+
* receiving. `bigint` is part of `ReactNode` under these React types, so
|
|
13
|
+
* leaving it out made a label React draws as text get treated as a rich node.
|
|
14
|
+
* React 18 cannot render one, which `DFormLabel` handles by rendering its
|
|
15
|
+
* string form — the classification stays true for every supported React.
|
|
16
|
+
*/
|
|
17
|
+
export default function isTextLabel(label: ReactNode): label is string | number | bigint;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Stops a click on a non-native trigger inside a `<label>` from also activating
|
|
4
|
+
* the labelled control.
|
|
5
|
+
*
|
|
6
|
+
* Verified against Chromium, which forwards the click for every one of the
|
|
7
|
+
* `PSEUDO_INTERACTIVE` selectors above while exempting the native ones. Note
|
|
8
|
+
* that jsdom does not reproduce this: its `isInteractiveContent` counts any
|
|
9
|
+
* element carrying a `tabindex` as interactive content, so a jsdom test passes
|
|
10
|
+
* whether or not this guard exists. That is why the guard is unit-tested
|
|
11
|
+
* directly rather than through a rendered component.
|
|
12
|
+
*
|
|
13
|
+
* Native interactive content returns early rather than falling through, since
|
|
14
|
+
* `preventDefault` on those clicks would cancel the link navigation or the
|
|
15
|
+
* image map the label is meant to let through.
|
|
16
|
+
*
|
|
17
|
+
* `DFormLabel` wires this in the capture phase so a trigger that stops
|
|
18
|
+
* propagation cannot skip it.
|
|
19
|
+
*/
|
|
20
|
+
export default function labelClickGuard(event: MouseEvent<HTMLLabelElement>): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
type WarnLabelUsageOptions = {
|
|
3
|
+
/** Component name, used to key the warning and to address the developer. */
|
|
4
|
+
component: string;
|
|
5
|
+
/** The `label` prop as received. */
|
|
6
|
+
label: ReactNode;
|
|
7
|
+
/** Whether an explicit accessible name reaches the control. */
|
|
8
|
+
hasAccessibleName: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The prop this component actually accepts for the accessible name, so the
|
|
11
|
+
* advice is usable: components that spread the native input attributes take
|
|
12
|
+
* `aria-label`, the rest expose the camelCase `ariaLabel` and reject the
|
|
13
|
+
* native one at compile time.
|
|
14
|
+
*/
|
|
15
|
+
accessibleNameProp: 'aria-label' | 'ariaLabel';
|
|
16
|
+
/** Whether the component is rendering in Bootstrap's floating-label layout. */
|
|
17
|
+
floatingLabel?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Warns, only outside production builds, about the two ways a non-text `label`
|
|
21
|
+
* goes wrong.
|
|
22
|
+
*
|
|
23
|
+
* A text label doubles as the control's accessible name. A `ReactNode` one does
|
|
24
|
+
* not: the name becomes whatever the subtree happens to compute to, which for a
|
|
25
|
+
* label carrying a link or an icon trigger reads as the wrong thing or as
|
|
26
|
+
* nothing at all — so an explicit name is needed. Which prop carries it differs
|
|
27
|
+
* per component, hence `accessibleNameProp`: naming the wrong one would send
|
|
28
|
+
* the developer to a prop their component rejects.
|
|
29
|
+
*
|
|
30
|
+
* `form-floating` is the second case: it animates a single line of text between
|
|
31
|
+
* the placeholder and the label position, so a node with its own height or its
|
|
32
|
+
* own interactive children breaks the layout rather than the semantics.
|
|
33
|
+
*
|
|
34
|
+
* Labels the render paths drop are skipped through the same `hasLabelContent`
|
|
35
|
+
* they use, so `label={condition && <span />}` with a false condition warns
|
|
36
|
+
* about nothing: there is no label on the page to name.
|
|
37
|
+
*
|
|
38
|
+
* The `process.env.NODE_ENV` guard belongs at the call site — that is what
|
|
39
|
+
* bundlers constant-fold, dropping this module from a consumer's production
|
|
40
|
+
* bundle.
|
|
41
|
+
*/
|
|
42
|
+
export default function warnLabelUsage({ component, label, hasAccessibleName, accessibleNameProp, floatingLabel, }: WarnLabelUsageOptions): void;
|
|
43
|
+
export {};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"sideEffects": [
|
|
4
4
|
"*.css"
|
|
5
5
|
],
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.11.0",
|
|
7
7
|
"description": "React Dynamic Framework",
|
|
8
8
|
"license": "https://github.com/dynamic-framework/dynamic-ui/blob/master/LICENSE.md",
|
|
9
9
|
"repository": {
|
|
@@ -45,11 +45,12 @@
|
|
|
45
45
|
"test:coverage": "jest --testPathPatterns=\\.spec\\.tsx?$ --coverage",
|
|
46
46
|
"test:a11y": "jest --testPathPatterns=\\.a11y\\.test\\.tsx$",
|
|
47
47
|
"test:storybook": "test-storybook",
|
|
48
|
-
"build": "npm run clean && npm run build:react && npm run build:scss && npm run build:icons-core && npm run cp",
|
|
48
|
+
"build": "npm run clean && npm run build:react && npm run build:scss && npm run build:icons-core && npm run build:api && npm run cp",
|
|
49
49
|
"build:react": "tsc -p ./tsconfig.build.json && rollup -c rollup.config.mjs",
|
|
50
50
|
"build:react:watch": "tsc -p ./tsconfig.build.json && rollup -c rollup.config.mjs",
|
|
51
51
|
"build:scss": "node scripts/build-scss.js",
|
|
52
52
|
"build:icons-core": "npx tsx scripts/build-icons-core.ts",
|
|
53
|
+
"build:api": "node scripts/generate-api.mjs && mkdir -p dist && cp registry/api.json dist/api.json",
|
|
53
54
|
"build:scss:watch": "npx nodemon --watch src --ext scss --exec 'npm run build:scss'",
|
|
54
55
|
"dev:ts": "tsc -p tsconfig.build.json",
|
|
55
56
|
"dev:rollup": "rollup -c rollup.config.mjs",
|
|
@@ -67,6 +68,9 @@
|
|
|
67
68
|
"validate:registry": "node scripts/validate-registry.mjs",
|
|
68
69
|
"generate:token-overrides": "node scripts/generate-token-overrides.mjs && node scripts/generate-token-overrides-schema.mjs",
|
|
69
70
|
"validate:token-overrides": "node scripts/validate-token-overrides.mjs",
|
|
71
|
+
"theme:expand": "node scripts/theme/theme-expand.mjs",
|
|
72
|
+
"theme:validate": "node scripts/theme/theme-validate.mjs",
|
|
73
|
+
"theme:preview": "vite scripts/theme --port 4173 --open /preview/",
|
|
70
74
|
"eslint": "npm run eslint:src && npm run eslint:stories && npm run eslint:test",
|
|
71
75
|
"eslint:src": "eslint 'src/**/*.ts' 'src/**/*.tsx' --ignore-pattern '**/*.spec.tsx'",
|
|
72
76
|
"eslint:stories": "eslint stories/**/*.stories.tsx",
|
|
@@ -75,7 +79,7 @@
|
|
|
75
79
|
"postversion": "npm run build:scss",
|
|
76
80
|
"publish:cdn": "npm run publish:cdn-version && npm run publish:cdn-latest",
|
|
77
81
|
"publish:cdn-version": "node scripts/publish-cdn.js",
|
|
78
|
-
"publish:cdn-latest": "aws s3 sync ./dist/ s3://dynamicframework-cdn/assets/latest/ui-react --delete --exclude 'api.json' --acl public-read",
|
|
82
|
+
"publish:cdn-latest": "aws s3 sync ./dist/ s3://dynamicframework-cdn/assets/latest/ui-react --delete --exclude 'api.json' --exclude 'manifests/*' --acl public-read",
|
|
79
83
|
"publish:cdn-rc": "aws s3 sync ./dist/ s3://dynamicframework-cdn/assets/rc/ui-react --delete --acl public-read",
|
|
80
84
|
"publish:cdn-dev": "aws s3 sync ./dist/ s3://dynamicframework-cdn/assets/dev/ui-react --delete --acl public-read",
|
|
81
85
|
"lint-staged": "lint-staged",
|
|
@@ -145,6 +149,7 @@
|
|
|
145
149
|
"autoprefixer": "~10.4.16",
|
|
146
150
|
"axe-playwright": "~1.2.3",
|
|
147
151
|
"conventional-changelog-conventionalcommits": "~6.1.0",
|
|
152
|
+
"culori": "^4.0.2",
|
|
148
153
|
"eslint": "~8.52.0",
|
|
149
154
|
"eslint-config-airbnb": "~19.0.4",
|
|
150
155
|
"eslint-config-airbnb-typescript": "~17.1.0",
|
|
@@ -17,10 +17,10 @@ $body-color: map-get($all-colors, $body-color-mapping) !default;
|
|
|
17
17
|
$body-bg: #f5f6fa !default;
|
|
18
18
|
|
|
19
19
|
$body-secondary-color: var(--#{$prefix}body-color-rgb) !default;
|
|
20
|
-
$body-secondary-bg: var(--#{$prefix}gray-200) !default;
|
|
20
|
+
$body-secondary-bg: var(--#{$prefix}gray-200-rgb) !default;
|
|
21
21
|
|
|
22
22
|
$body-tertiary-color: var(--#{$prefix}body-color-rgb) !default;
|
|
23
|
-
$body-tertiary-bg: var(--#{$prefix}gray-100) !default;
|
|
23
|
+
$body-tertiary-bg: var(--#{$prefix}gray-100-rgb) !default;
|
|
24
24
|
|
|
25
25
|
$body-emphasis-color: var(--#{$prefix}black-rgb) !default;
|
|
26
26
|
// end custom
|
|
@@ -10,4 +10,6 @@ $chip-padding-y: $spacer-1 !default;
|
|
|
10
10
|
$chip-font-size: $small-font-size !default;
|
|
11
11
|
$chip-font-weight: $font-weight-bold !default;
|
|
12
12
|
$chip-line-height: $line-height-base !default;
|
|
13
|
+
$chip-icon-container-size: 1lh !default;
|
|
14
|
+
$chip-icon-container-size-fallback: $line-height-base * 1em !default;
|
|
13
15
|
// scss-docs-end chip-variables
|
|
@@ -404,7 +404,7 @@ $info-text-emphasis: var(--#{$prefix}info-600) !default;
|
|
|
404
404
|
$warning-text-emphasis: var(--#{$prefix}warning-800) !default;
|
|
405
405
|
$danger-text-emphasis: var(--#{$prefix}danger-600) !default;
|
|
406
406
|
$light-text-emphasis: var(--#{$prefix}gray-600) !default;
|
|
407
|
-
$dark-text-emphasis: var(--#{$prefix}gray-
|
|
407
|
+
$dark-text-emphasis: var(--#{$prefix}gray-900) !default;
|
|
408
408
|
// scss-docs-end theme-text-variables
|
|
409
409
|
|
|
410
410
|
// scss-docs-start theme-bg-subtle-variables
|
|
@@ -415,7 +415,7 @@ $info-bg-subtle: var(--#{$prefix}info-25) !default;
|
|
|
415
415
|
$warning-bg-subtle: var(--#{$prefix}warning-25) !default;
|
|
416
416
|
$danger-bg-subtle: var(--#{$prefix}danger-25) !default;
|
|
417
417
|
$light-bg-subtle: var(--#{$prefix}gray-100) !default;
|
|
418
|
-
$dark-bg-subtle: var(--#{$prefix}gray-
|
|
418
|
+
$dark-bg-subtle: var(--#{$prefix}gray-300) !default;
|
|
419
419
|
// scss-docs-end theme-bg-subtle-variables
|
|
420
420
|
|
|
421
421
|
// scss-docs-start theme-border-subtle-variables
|
|
@@ -149,8 +149,11 @@
|
|
|
149
149
|
@include box-shadow(none);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
// The glyph follows the button's font size unless a size is set explicitly,
|
|
153
|
+
// through DIcon's `size` (inline) or `--bs-icon-component-size` on the icon
|
|
154
|
+
// or the button.
|
|
152
155
|
.d-icon {
|
|
153
|
-
--#{$prefix}icon-size: var(--#{$prefix}btn-font-size);
|
|
156
|
+
--#{$prefix}icon-size: var(--#{$prefix}icon-component-size, var(--#{$prefix}btn-font-size));
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
|
|
@@ -71,11 +71,14 @@
|
|
|
71
71
|
--#{$prefix}input-group-sm-icon-size: #{$input-group-sm-icon-size};
|
|
72
72
|
--#{$prefix}input-group-lg-icon-size: #{$input-group-lg-icon-size};
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
// Icons inside a button (a DButton or DButtonIcon in `inputStart`/`inputEnd`)
|
|
75
|
+
// keep following the button's font size, as before `.btn .d-icon` honored
|
|
76
|
+
// an explicit icon size.
|
|
77
|
+
&.input-group-sm .d-icon:not(.btn .d-icon) {
|
|
75
78
|
--#{$prefix}icon-component-size: var(--#{$prefix}input-group-sm-icon-size);
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
&.input-group-lg .d-icon {
|
|
81
|
+
&.input-group-lg .d-icon:not(.btn .d-icon) {
|
|
79
82
|
--#{$prefix}icon-component-size: var(--#{$prefix}input-group-lg-icon-size);
|
|
80
83
|
}
|
|
81
84
|
|
|
@@ -4,3 +4,58 @@
|
|
|
4
4
|
gap: var(--#{$prefix}list-group-item-gap);
|
|
5
5
|
align-items: center;
|
|
6
6
|
}
|
|
7
|
+
|
|
8
|
+
// Interactive item inside a list: the <li> is the visual item (borders,
|
|
9
|
+
// colors, active/disabled) and the link or button fills it, so the group keeps
|
|
10
|
+
// `ul/ol > li` semantics and Bootstrap's sibling selectors still apply.
|
|
11
|
+
.d-list-group-item-interactive {
|
|
12
|
+
padding: 0;
|
|
13
|
+
|
|
14
|
+
&:not(.active):focus-within {
|
|
15
|
+
z-index: 1;
|
|
16
|
+
color: var(--#{$prefix}list-group-action-hover-color);
|
|
17
|
+
background-color: var(--#{$prefix}list-group-action-hover-bg);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.d-list-group-item-link {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex: 1 1 auto;
|
|
24
|
+
gap: var(--#{$prefix}list-group-item-gap);
|
|
25
|
+
align-items: center;
|
|
26
|
+
align-self: stretch;
|
|
27
|
+
width: 100%;
|
|
28
|
+
padding: var(--#{$prefix}list-group-item-padding-y) var(--#{$prefix}list-group-item-padding-x);
|
|
29
|
+
font: inherit;
|
|
30
|
+
color: inherit;
|
|
31
|
+
text-align: inherit;
|
|
32
|
+
text-decoration: none;
|
|
33
|
+
background-color: transparent;
|
|
34
|
+
border: 0;
|
|
35
|
+
border-radius: inherit;
|
|
36
|
+
|
|
37
|
+
&:hover {
|
|
38
|
+
color: inherit;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// In a numbered list the counter goes inside the link or button, so the whole
|
|
43
|
+
// row, number included, is clickable. The <li> drops its own counter.
|
|
44
|
+
.list-group-numbered > .list-group-item.d-list-group-item-interactive::before {
|
|
45
|
+
content: none;
|
|
46
|
+
counter-increment: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.list-group-numbered > .d-list-group-item-interactive > .d-list-group-item-link::before {
|
|
50
|
+
content: counters(section, ".") ". ";
|
|
51
|
+
content: counters(section, ".") ". " / "";
|
|
52
|
+
counter-increment: section;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The generated number is decoration: an <ol> already announces the position,
|
|
56
|
+
// so screen readers skip it (the second declaration uses the alt-text syntax;
|
|
57
|
+
// browsers without it keep the first).
|
|
58
|
+
.list-group-numbered > .list-group-item::before {
|
|
59
|
+
content: counters(section, ".") ". ";
|
|
60
|
+
content: counters(section, ".") ". " / "";
|
|
61
|
+
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
--#{$prefix}chip-font-size: #{$chip-font-size};
|
|
9
9
|
--#{$prefix}chip-font-weight: #{$chip-font-weight};
|
|
10
10
|
--#{$prefix}chip-line-height: #{$chip-line-height};
|
|
11
|
+
--#{$prefix}chip-icon-container-size: #{$chip-icon-container-size};
|
|
11
12
|
|
|
12
13
|
display: inline-flex;
|
|
13
14
|
flex-direction: row;
|
|
@@ -29,14 +30,18 @@
|
|
|
29
30
|
display: flex;
|
|
30
31
|
align-items: center;
|
|
31
32
|
justify-content: center;
|
|
32
|
-
width: var(--#{$prefix}chip-
|
|
33
|
-
height: var(--#{$prefix}chip-
|
|
33
|
+
width: var(--#{$prefix}chip-icon-container-size);
|
|
34
|
+
height: var(--#{$prefix}chip-icon-container-size);
|
|
34
35
|
padding: 0;
|
|
35
36
|
margin: 0;
|
|
36
37
|
background: transparent;
|
|
37
38
|
border: 0;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
@supports not (width: 1lh) {
|
|
42
|
+
--#{$prefix}chip-icon-container-size: #{$chip-icon-container-size-fallback};
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
@each $theme, $value in map-remove($theme-colors, "light", "dark", "warning") {
|
|
41
46
|
$color: color-contrast($value);
|
|
42
47
|
&.d-chip-#{$theme} {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
.d-tabs {
|
|
2
|
+
--#{$prefix}tabs-content-margin-bottom: var(--#{$prefix}ref-spacer-4);
|
|
3
|
+
|
|
2
4
|
display: flex;
|
|
3
5
|
width: 100%;
|
|
4
6
|
}
|
|
@@ -14,6 +16,7 @@
|
|
|
14
16
|
|
|
15
17
|
.d-tabs-content {
|
|
16
18
|
width: 100%;
|
|
19
|
+
margin-bottom: var(--#{$prefix}tabs-content-margin-bottom);
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
.nav-toggle-button-group {
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
color: var(--#{$prefix}secondary-700);
|
|
6
6
|
background: var(--#{$prefix}secondary-50);
|
|
7
7
|
}
|
|
8
|
+
} @else if map-has-key($theme-colors, $color) {
|
|
9
|
+
.text-bg-#{$color} {
|
|
10
|
+
color: var(--#{$prefix}#{$color}-text-bg-color) if($enable-important-utilities, !important, null);
|
|
11
|
+
background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1)) if($enable-important-utilities, !important, null);
|
|
12
|
+
}
|
|
8
13
|
} @else {
|
|
9
14
|
.text-bg-#{$color} {
|
|
10
15
|
color: color-contrast-var($value) if($enable-important-utilities, !important, null);
|
|
@@ -71,6 +71,15 @@
|
|
|
71
71
|
--#{$prefix}#{$color}-border-subtle: #{$value};
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// Text color of `.text-bg-<color>`, resolved in Sass against the default
|
|
75
|
+
// role value. It lives in a variable so a theme that redefines
|
|
76
|
+
// `--bs-<color>-rgb` can move it too. `secondary` already reads its ramp.
|
|
77
|
+
@each $color, $value in $theme-colors {
|
|
78
|
+
@if $color != "secondary" {
|
|
79
|
+
--#{$prefix}#{$color}-text-bg-color: #{color-contrast-var($value)};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
74
83
|
// Fonts
|
|
75
84
|
|
|
76
85
|
// Note: Use `inspect` for lists so that quoted items keep the quotes.
|