@autoguru/overdrive 4.62.0 → 4.64.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/components/Alert/Alert.d.ts +4 -1
- package/dist/components/Alert/Alert.d.ts.map +1 -1
- package/dist/components/Alert/Alert.js +11 -5
- package/dist/components/Button/Button.css.d.ts +13 -1
- package/dist/components/Button/Button.css.d.ts.map +1 -1
- package/dist/components/Button/Button.css.js +35 -0
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/Button.js +5 -1
- package/dist/components/CheckBox/CheckBox.css.d.ts.map +1 -1
- package/dist/components/CheckBox/CheckBox.css.js +5 -2
- package/dist/components/FilterChip/FilterChip.css.d.ts +64 -0
- package/dist/components/FilterChip/FilterChip.css.d.ts.map +1 -0
- package/dist/components/FilterChip/FilterChip.css.js +243 -0
- package/dist/components/FilterChip/FilterChip.d.ts +112 -0
- package/dist/components/FilterChip/FilterChip.d.ts.map +1 -0
- package/dist/components/FilterChip/FilterChip.js +152 -0
- package/dist/components/FilterChip/default.d.ts +2 -0
- package/dist/components/FilterChip/default.d.ts.map +1 -0
- package/dist/components/FilterChip/default.js +1 -0
- package/dist/components/FilterChip/index.d.ts +3 -0
- package/dist/components/FilterChip/index.d.ts.map +1 -0
- package/dist/components/FilterChip/index.js +1 -0
- package/dist/components/MinimalModal/MinimalModal.css.js +4 -4
- package/dist/components/OverdriveProvider/OverdriveProvider.d.ts +13 -1
- package/dist/components/OverdriveProvider/OverdriveProvider.d.ts.map +1 -1
- package/dist/components/OverdriveProvider/OverdriveProvider.js +6 -1
- package/dist/components/OverdriveProvider/useColorOverrides.d.ts +3 -2
- package/dist/components/OverdriveProvider/useColorOverrides.d.ts.map +1 -1
- package/dist/components/OverdriveProvider/useColorOverrides.js +158 -22
- package/dist/components/OverdriveProvider/useColorOverrides.spec.d.ts +2 -0
- package/dist/components/OverdriveProvider/useColorOverrides.spec.d.ts.map +1 -0
- package/dist/components/OverdriveProvider/useColorOverrides.spec.js +226 -0
- package/dist/components/Radio/Radio.css.d.ts.map +1 -1
- package/dist/components/Radio/Radio.css.js +3 -2
- package/dist/components/StandardModal/StandardModal.css.js +2 -2
- package/dist/components/StandardModal/StandardModal.js +3 -2
- package/dist/components/Switch/Switch.css.d.ts.map +1 -1
- package/dist/components/Switch/Switch.css.js +3 -1
- package/dist/components/Tabs/Tab.css.d.ts +40 -0
- package/dist/components/Tabs/Tab.css.d.ts.map +1 -1
- package/dist/components/Tabs/Tab.css.js +69 -8
- package/dist/components/Tabs/Tab.js +1 -1
- package/dist/components/Tabs/TabList.css.d.ts +1 -0
- package/dist/components/Tabs/TabList.css.d.ts.map +1 -1
- package/dist/components/Tabs/TabList.css.js +2 -1
- package/dist/components/Tabs/TabList.d.ts.map +1 -1
- package/dist/components/Tabs/TabList.js +5 -2
- package/dist/components/Tabs/TabPane.js +2 -1
- package/dist/components/Tabs/TabPanes.js +2 -1
- package/dist/components/Tabs/Tabs.d.ts +2 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/components/Tabs/Tabs.js +4 -1
- package/dist/components/Tabs/index.d.ts +4 -3
- package/dist/components/Tabs/index.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/styles/intentColorset.css.d.ts +3 -3
- package/dist/styles/sprinkles.css.d.ts +12 -12
- package/dist/styles/typography.css.d.ts +1 -1
- package/dist/themes/base/contrastGuide.spec.js +11 -2
- package/dist/themes/base/index.d.ts +8 -0
- package/dist/themes/base/index.d.ts.map +1 -1
- package/dist/themes/base/tokens.d.ts +17 -0
- package/dist/themes/base/tokens.d.ts.map +1 -1
- package/dist/themes/base/tokens.js +18 -0
- package/dist/themes/flat_red/index.d.ts +13 -0
- package/dist/themes/flat_red/index.d.ts.map +1 -1
- package/dist/themes/flat_red/tokens.d.ts +9 -0
- package/dist/themes/flat_red/tokens.d.ts.map +1 -1
- package/dist/themes/flat_red/tokens.js +10 -0
- package/dist/themes/index.d.ts +8 -0
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/makeTheme.d.ts +4 -0
- package/dist/themes/makeTheme.d.ts.map +1 -1
- package/dist/themes/neutral/index.d.ts +13 -0
- package/dist/themes/neutral/index.d.ts.map +1 -1
- package/dist/themes/neutral/tokens.d.ts +9 -0
- package/dist/themes/neutral/tokens.d.ts.map +1 -1
- package/dist/themes/neutral/tokens.js +11 -0
- package/dist/themes/theme.css.d.ts +4 -0
- package/dist/themes/theme.css.d.ts.map +1 -1
- package/dist/themes/theme.css.js +16 -0
- package/package.json +1 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
2
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
|
3
|
+
const _excluded = ["type", "label", "value", "operator", "selected", "pressed", "expanded", "onClick", "onRemove", "removeLabel", "className", "testId", "aria-haspopup"];
|
|
4
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
5
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6
|
+
import { PlusIcon, XIcon } from '@autoguru/icons';
|
|
7
|
+
import clsx from 'clsx';
|
|
8
|
+
import React, { forwardRef } from 'react';
|
|
9
|
+
import { useNullCheck } from "../../hooks/useNullCheck/index.js";
|
|
10
|
+
import { useBox } from "../Box/useBox/useBox.js";
|
|
11
|
+
import { Icon } from "../Icon/Icon.js";
|
|
12
|
+
import * as styles from "./FilterChip.css.js";
|
|
13
|
+
/** Attributes forwarded to the chip body. */
|
|
14
|
+
/** The props every chip except `add` shares. */
|
|
15
|
+
/** A category and its chosen value, e.g. `Vehicle type: Truck`. */
|
|
16
|
+
/** A category, a comparison operator and a value, e.g. `Usage (km): over 100,000 km`. */
|
|
17
|
+
/** A bare label with no value, e.g. `Serviced`. */
|
|
18
|
+
/**
|
|
19
|
+
* The dashed "Add Filter" affordance that opens a filter picker. It holds no
|
|
20
|
+
* filter, so it takes no value, no state and nothing to remove, and `onClick` is
|
|
21
|
+
* required.
|
|
22
|
+
*/
|
|
23
|
+
/** All FilterChip props, discriminated on `type`. */
|
|
24
|
+
/**
|
|
25
|
+
* The four filter chip shapes.
|
|
26
|
+
*
|
|
27
|
+
* - `select` — a category and its chosen value, e.g. `Vehicle type: Truck`
|
|
28
|
+
* - `numeric` — a category, a comparison operator and a value, e.g. `Usage (km): over 100,000 km`
|
|
29
|
+
* - `simple` — a bare label with no value
|
|
30
|
+
* - `add` — the dashed "Add Filter" affordance that opens a filter picker
|
|
31
|
+
*/
|
|
32
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
33
|
+
/**
|
|
34
|
+
* A filter chip represents one active filter in a filter bar. The body opens an
|
|
35
|
+
* editor for the filter's value and the trailing `×` clears it.
|
|
36
|
+
*
|
|
37
|
+
* Distinct from `Badge`, which is a static, non-interactive label.
|
|
38
|
+
*
|
|
39
|
+
* The forwarded `ref` lands on the chip body, which is what a `Popover` anchors
|
|
40
|
+
* to. It is attached only when the body is a button — that is, when `onClick` is
|
|
41
|
+
* supplied. A chip without one has an inert `<span>` body and receives no ref,
|
|
42
|
+
* whether or not it has a `×`.
|
|
43
|
+
*
|
|
44
|
+
* Removal is by the `×` button only — the WAI-ARIA APG chip pattern also removes
|
|
45
|
+
* a focused chip on `Backspace`/`Delete`, which this component does not
|
|
46
|
+
* implement.
|
|
47
|
+
*/
|
|
48
|
+
export const FilterChip = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
49
|
+
let {
|
|
50
|
+
type = 'select',
|
|
51
|
+
label,
|
|
52
|
+
value,
|
|
53
|
+
operator,
|
|
54
|
+
selected = false,
|
|
55
|
+
pressed,
|
|
56
|
+
expanded,
|
|
57
|
+
onClick,
|
|
58
|
+
onRemove,
|
|
59
|
+
removeLabel,
|
|
60
|
+
className,
|
|
61
|
+
testId,
|
|
62
|
+
'aria-haspopup': ariaHasPopup
|
|
63
|
+
} = _ref,
|
|
64
|
+
bodyAttrs = _objectWithoutProperties(_ref, _excluded);
|
|
65
|
+
const isAdd = type === 'add';
|
|
66
|
+
const isSelected = !isAdd && selected;
|
|
67
|
+
const showRemove = !isAdd && typeof onRemove === 'function';
|
|
68
|
+
const isInteractive = typeof onClick === 'function' || showRemove;
|
|
69
|
+
useNullCheck(!isAdd || typeof onClick === 'function', 'FilterChip: an "add" chip needs an onClick — without one it renders as static text that still looks like a button.');
|
|
70
|
+
useNullCheck(typeof onClick === 'function' || expanded === undefined && pressed === undefined, 'FilterChip: "expanded" and "pressed" describe the chip body, which is only a button when onClick is supplied. Without one they are dropped.');
|
|
71
|
+
const accessibleName = label.replace(/:\s*$/, '');
|
|
72
|
+
const removeName = [accessibleName, operator, value].filter(Boolean).join(' ');
|
|
73
|
+
const stateProps = {
|
|
74
|
+
'aria-expanded': expanded,
|
|
75
|
+
'aria-haspopup': ariaHasPopup !== null && ariaHasPopup !== void 0 ? ariaHasPopup : expanded === undefined ? undefined : true,
|
|
76
|
+
'aria-pressed': isAdd ? undefined : pressed
|
|
77
|
+
};
|
|
78
|
+
const isBodyButton = typeof onClick === 'function';
|
|
79
|
+
const bodyInteractionProps = isBodyButton ? _objectSpread(_objectSpread({}, stateProps), {}, {
|
|
80
|
+
onClick,
|
|
81
|
+
ref,
|
|
82
|
+
type: 'button'
|
|
83
|
+
}) : {};
|
|
84
|
+
const bodyAs = isBodyButton ? 'button' : 'span';
|
|
85
|
+
const rootAs = showRemove ? 'div' : bodyAs;
|
|
86
|
+
const {
|
|
87
|
+
Component: Root,
|
|
88
|
+
componentProps: rootProps
|
|
89
|
+
} = useBox(_objectSpread({
|
|
90
|
+
as: rootAs,
|
|
91
|
+
className: [styles.chip({
|
|
92
|
+
variant: isAdd ? 'add' : 'filter',
|
|
93
|
+
selected: isSelected,
|
|
94
|
+
interactive: isInteractive
|
|
95
|
+
}), !showRemove && styles.chipBody(), !showRemove && isBodyButton && styles.buttonFont, className],
|
|
96
|
+
odComponent: 'filter-chip',
|
|
97
|
+
testId
|
|
98
|
+
}, showRemove ? {} : _objectSpread(_objectSpread({}, bodyAttrs), bodyInteractionProps)));
|
|
99
|
+
const {
|
|
100
|
+
Component: Body,
|
|
101
|
+
componentProps: bodyProps
|
|
102
|
+
} = useBox(_objectSpread(_objectSpread({
|
|
103
|
+
as: bodyAs,
|
|
104
|
+
className: [styles.chipBody({
|
|
105
|
+
withRemove: true
|
|
106
|
+
}), styles.innerButtonText, isBodyButton && styles.buttonFont]
|
|
107
|
+
}, bodyAttrs), bodyInteractionProps));
|
|
108
|
+
const {
|
|
109
|
+
Component: Remove,
|
|
110
|
+
componentProps: removeProps
|
|
111
|
+
} = useBox({
|
|
112
|
+
as: 'button',
|
|
113
|
+
className: [styles.buttonFont, styles.innerButtonText, styles.removeButton],
|
|
114
|
+
'aria-label': removeLabel !== null && removeLabel !== void 0 ? removeLabel : `Remove ${removeName} filter`,
|
|
115
|
+
onClick: onRemove,
|
|
116
|
+
type: 'button'
|
|
117
|
+
});
|
|
118
|
+
const content = /*#__PURE__*/_jsxs(_Fragment, {
|
|
119
|
+
children: [isAdd && /*#__PURE__*/_jsx(Icon, {
|
|
120
|
+
icon: PlusIcon,
|
|
121
|
+
size: "small"
|
|
122
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
123
|
+
className: clsx(styles.labelText, (type === 'select' || type === 'numeric') && styles.categoryLabel({
|
|
124
|
+
selected: isSelected
|
|
125
|
+
})),
|
|
126
|
+
children: label
|
|
127
|
+
}), type === 'numeric' && operator ? /*#__PURE__*/_jsx("span", {
|
|
128
|
+
className: styles.labelText,
|
|
129
|
+
children: operator
|
|
130
|
+
}) : null, (type === 'select' || type === 'numeric') && value ? /*#__PURE__*/_jsx("span", {
|
|
131
|
+
className: styles.valueText,
|
|
132
|
+
title: value,
|
|
133
|
+
children: value
|
|
134
|
+
}) : null]
|
|
135
|
+
});
|
|
136
|
+
if (showRemove) {
|
|
137
|
+
return /*#__PURE__*/_jsxs(Root, _objectSpread(_objectSpread({}, rootProps), {}, {
|
|
138
|
+
children: [/*#__PURE__*/_jsx(Body, _objectSpread(_objectSpread({}, bodyProps), {}, {
|
|
139
|
+
children: content
|
|
140
|
+
})), /*#__PURE__*/_jsx(Remove, _objectSpread(_objectSpread({}, removeProps), {}, {
|
|
141
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
142
|
+
icon: XIcon,
|
|
143
|
+
size: "small"
|
|
144
|
+
})
|
|
145
|
+
}))]
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
return /*#__PURE__*/_jsx(Root, _objectSpread(_objectSpread({}, rootProps), {}, {
|
|
149
|
+
children: content
|
|
150
|
+
}));
|
|
151
|
+
});
|
|
152
|
+
FilterChip.displayName = 'FilterChip';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../lib/components/FilterChip/default.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FilterChip as default } from "./FilterChip.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/components/FilterChip/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FilterChip } from "./FilterChip.js";
|
|
@@ -10,12 +10,12 @@ export const content = style({
|
|
|
10
10
|
overscrollBehavior: 'contain'
|
|
11
11
|
}, "content");
|
|
12
12
|
const borderRoundTop = style({
|
|
13
|
-
borderTopLeftRadius: tokens.border.radius
|
|
14
|
-
borderTopRightRadius: tokens.border.radius
|
|
13
|
+
borderTopLeftRadius: tokens.border.radius.medium,
|
|
14
|
+
borderTopRightRadius: tokens.border.radius.medium
|
|
15
15
|
}, "borderRoundTop");
|
|
16
16
|
const borderRoundBottom = style({
|
|
17
|
-
borderBottomLeftRadius: tokens.border.radius
|
|
18
|
-
borderBottomRightRadius: tokens.border.radius
|
|
17
|
+
borderBottomLeftRadius: tokens.border.radius.medium,
|
|
18
|
+
borderBottomRightRadius: tokens.border.radius.medium
|
|
19
19
|
}, "borderRoundBottom");
|
|
20
20
|
export const borders = styleVariants({
|
|
21
21
|
center: [borderRoundTop, borderRoundBottom],
|
|
@@ -14,7 +14,19 @@ export interface ProviderProps {
|
|
|
14
14
|
breakpoints?: BreakPoints;
|
|
15
15
|
/** When true, prevents applying theme styles at the body level */
|
|
16
16
|
noBodyLevelTheming?: boolean;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Custom colour overrides for select theme tokens — the runtime brand hook.
|
|
19
|
+
*
|
|
20
|
+
* `primaryBackground` drives the primary Button, the brand accent behind
|
|
21
|
+
* Switch/Radio/CheckBox on-states, the outlined Button, and
|
|
22
|
+
* `<Text colour="primary">`. `primaryForeground` is the content placed on
|
|
23
|
+
* top of it; when omitted it is derived for contrast.
|
|
24
|
+
*
|
|
25
|
+
* `linkColor` is deliberately separate rather than following
|
|
26
|
+
* `primaryBackground`: it also drives every focus ring in the library, and a
|
|
27
|
+
* colour picked as a fill behind white text is often illegible as link text
|
|
28
|
+
* on the page background. Pass it explicitly to brand links.
|
|
29
|
+
*/
|
|
18
30
|
colorOverrides?: Partial<ColorOverrides>;
|
|
19
31
|
/** Reference to an HTML element where portals should be mounted */
|
|
20
32
|
portalMountPoint?: PortalMountPoint;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverdriveProvider.d.ts","sourceRoot":"","sources":["../../../lib/components/OverdriveProvider/OverdriveProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAwD,MAAM,OAAO,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E,KAAK,aAAa,GAAG,OAAO,eAAe,CAAC;AAC5C,KAAK,gBAAgB,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAqC5D,MAAM,WAAW,aAAa;IAC7B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,SAAS,CAAC;IACzB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B
|
|
1
|
+
{"version":3,"file":"OverdriveProvider.d.ts","sourceRoot":"","sources":["../../../lib/components/OverdriveProvider/OverdriveProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAwD,MAAM,OAAO,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E,KAAK,aAAa,GAAG,OAAO,eAAe,CAAC;AAC5C,KAAK,gBAAgB,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAqC5D,MAAM,WAAW,aAAa;IAC7B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,SAAS,CAAC;IACzB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,eAChB,SAAQ,IAAI,CAAC,aAAa,EAAE,gBAAgB,GAAG,kBAAkB,CAAC;IAClE,UAAU,EAAE,CAAC,OAAO,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IACpD,IAAI,EAAE,aAAa,CAAC;CACpB;AAMD,eAAO,MAAM,QAAQ,uBAIpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,aAInC,CAAC;AAUF,eAAO,MAAM,QAAQ,GAAI,iGAQtB,aAAa,sBAkEf,CAAC;AAEF,eAAO,MAAM,iBAAiB,2CAK7B,CAAC"}
|
|
@@ -66,7 +66,12 @@ export const Provider = ({
|
|
|
66
66
|
theme = baseTheme
|
|
67
67
|
}) => {
|
|
68
68
|
const runtimeTokens = useMemo(() => makeRuntimeTokens(breakpoints), [breakpoints]);
|
|
69
|
-
|
|
69
|
+
// The theme's resolved tokens, not `theme.vars` — those are CSS var
|
|
70
|
+
// *references* (`var(--od-mode)`), so the mode check downstream never
|
|
71
|
+
// matched and its light/dark branch was dead. Passing the tokens also lets
|
|
72
|
+
// contrast decisions be made against this theme's own page background and
|
|
73
|
+
// body ink rather than the base theme's.
|
|
74
|
+
const styles = useColorOverrides(colorOverrides, theme.tokens);
|
|
70
75
|
const themeValues = useMemo(() => ({
|
|
71
76
|
themeClass: theme.themeRef,
|
|
72
77
|
themeName: theme.name,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { type ThemeTokens } from '../../themes/theme.css';
|
|
1
2
|
/** valid colour override keys */
|
|
2
|
-
declare const colorOverrideKeys: readonly ["primaryBackground", "primaryBackgroundMild", "primaryBackgroundStrong", "primaryBorder", "primaryForeground"];
|
|
3
|
+
declare const colorOverrideKeys: readonly ["primaryBackground", "primaryBackgroundMild", "primaryBackgroundStrong", "primaryBorder", "primaryForeground", "linkColor"];
|
|
3
4
|
export type ColorOverrides = Record<(typeof colorOverrideKeys)[number], string>;
|
|
4
|
-
export declare const useColorOverrides: (overrides: Partial<ColorOverrides> | undefined,
|
|
5
|
+
export declare const useColorOverrides: (overrides: Partial<ColorOverrides> | undefined, tokens: ThemeTokens) => {
|
|
5
6
|
[cssVarName: string]: string;
|
|
6
7
|
};
|
|
7
8
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useColorOverrides.d.ts","sourceRoot":"","sources":["../../../lib/components/OverdriveProvider/useColorOverrides.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useColorOverrides.d.ts","sourceRoot":"","sources":["../../../lib/components/OverdriveProvider/useColorOverrides.ts"],"names":[],"mappings":"AAQA,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAe3E,iCAAiC;AACjC,QAAA,MAAM,iBAAiB,uIAOb,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AAsFhF,eAAO,MAAM,iBAAiB,GAC7B,WAAW,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,EAC9C,QAAQ,WAAW;;CAgJnB,CAAC"}
|
|
@@ -1,71 +1,207 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1
4
|
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
|
2
5
|
import { useMemo } from 'react';
|
|
3
|
-
import { shadedColour } from "../../themes/helpers.js";
|
|
6
|
+
import { getContrastRatio, passesAccessibilityContrast, shadedColour } from "../../themes/helpers.js";
|
|
4
7
|
import { overdriveTokens } from "../../themes/theme.css.js";
|
|
8
|
+
/** The active theme's own values, so contrast decisions match what it renders. */
|
|
9
|
+
const themeContext = tokens => ({
|
|
10
|
+
mode: String(tokens.mode),
|
|
11
|
+
pageBackground: tokens.color.background.default,
|
|
12
|
+
bodyInk: tokens.color.foreground.primary
|
|
13
|
+
});
|
|
14
|
+
|
|
5
15
|
/** valid colour override keys */
|
|
6
|
-
const colorOverrideKeys = ['primaryBackground', 'primaryBackgroundMild', 'primaryBackgroundStrong', 'primaryBorder', 'primaryForeground'];
|
|
16
|
+
const colorOverrideKeys = ['primaryBackground', 'primaryBackgroundMild', 'primaryBackgroundStrong', 'primaryBorder', 'primaryForeground', 'linkColor'];
|
|
7
17
|
const isValidColor = color => {
|
|
18
|
+
// `Option` is a DOM global, so this throws during SSR. Failing closed there
|
|
19
|
+
// stripped every override, leaving the brand to appear only on hydration.
|
|
20
|
+
if (typeof Option === 'undefined') return true;
|
|
8
21
|
try {
|
|
9
22
|
const s = new Option();
|
|
10
23
|
s.style.color = color !== null && color !== void 0 ? color : '';
|
|
11
24
|
return s.style.color !== '';
|
|
12
25
|
} catch {
|
|
13
|
-
return
|
|
26
|
+
return true;
|
|
14
27
|
}
|
|
15
28
|
};
|
|
16
|
-
|
|
29
|
+
|
|
30
|
+
/** Warn once per message — the provider re-renders on every child change. */
|
|
31
|
+
const warned = new Set();
|
|
32
|
+
const warnOnce = message => {
|
|
33
|
+
if (warned.has(message)) return;
|
|
34
|
+
warned.add(message);
|
|
35
|
+
console.warn(message);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Contrast-safe content for a brand fill, chosen from the active theme's own
|
|
40
|
+
* page background and body ink.
|
|
41
|
+
*
|
|
42
|
+
* `getContrastRatio` returns `min/max` — the reciprocal of the WCAG ratio — so
|
|
43
|
+
* the SMALLER value wins.
|
|
44
|
+
*/
|
|
45
|
+
const onBrandColour = (brand, theme) => getContrastRatio(theme.pageBackground, brand) < getContrastRatio(theme.bodyInk, brand) ? theme.pageBackground : theme.bodyInk;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Prefer `primaryForeground`, but only while it clears 3:1 on the fill — it was
|
|
49
|
+
* chosen as a button label colour, and a light brand paired with white text
|
|
50
|
+
* would otherwise leave an invisible tick.
|
|
51
|
+
*/
|
|
52
|
+
const resolveOnBrand = (brand, theme, suppliedForeground) => {
|
|
53
|
+
if (!suppliedForeground) return onBrandColour(brand, theme);
|
|
54
|
+
const legible = passesAccessibilityContrast({
|
|
55
|
+
colour1: suppliedForeground,
|
|
56
|
+
colour2: brand,
|
|
57
|
+
level: 'AA',
|
|
58
|
+
textSize: 'LARGE'
|
|
59
|
+
});
|
|
60
|
+
if (legible) return suppliedForeground;
|
|
61
|
+
const derived = onBrandColour(brand, theme);
|
|
62
|
+
warnOnce(`Overdrive Provider: primaryForeground (${suppliedForeground}) does not meet 3:1 against primaryBackground (${brand}), so selection controls would be illegible. Using ${derived} for their tick/dot/knob instead.`);
|
|
63
|
+
return derived;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** Dev-only nudge for a colour drawn as text or a border on the page. */
|
|
67
|
+
const warnOnLowContrast = (colour, key, theme) => {
|
|
68
|
+
if (colour && !passesAccessibilityContrast({
|
|
69
|
+
colour1: colour,
|
|
70
|
+
colour2: theme.pageBackground,
|
|
71
|
+
level: 'AA',
|
|
72
|
+
textSize: 'SMALL'
|
|
73
|
+
})) {
|
|
74
|
+
warnOnce(`Overdrive Provider: ${key} (${colour}) does not meet WCAG AA (4.5:1) against the page background. Anything drawn in it as text or a border — outlined buttons, links, focus rings — may be hard to read.`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
export const useColorOverrides = (overrides, tokens) => {
|
|
17
78
|
return useMemo(() => {
|
|
18
|
-
var
|
|
79
|
+
var _onBrand, _outlinedHover, _outlinedPressed, _mildPrimary, _strongPrimary, _buttonForeground, _valid$primaryBorder;
|
|
19
80
|
if (!overrides) return {};
|
|
81
|
+
const theme = themeContext(tokens);
|
|
82
|
+
|
|
83
|
+
// Copy before pruning — callers commonly hold this object in a cache.
|
|
84
|
+
const valid = _objectSpread({}, overrides);
|
|
20
85
|
colorOverrideKeys.forEach(key => {
|
|
21
|
-
if (
|
|
22
|
-
console.warn(`Overdrive Provider: Invalid override color value for ${key}: ${
|
|
23
|
-
delete
|
|
86
|
+
if (valid[key] && !isValidColor(valid[key])) {
|
|
87
|
+
console.warn(`Overdrive Provider: Invalid override color value for ${key}: ${valid[key]}`);
|
|
88
|
+
delete valid[key];
|
|
24
89
|
}
|
|
25
90
|
});
|
|
91
|
+
const {
|
|
92
|
+
primaryBackground,
|
|
93
|
+
linkColor
|
|
94
|
+
} = valid;
|
|
95
|
+
// unknown modes degrade to light, the common case
|
|
96
|
+
const isDarkTheme = theme.mode === 'dark';
|
|
26
97
|
let mildPrimary = null;
|
|
27
98
|
let strongPrimary = null;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
99
|
+
let onBrand = null;
|
|
100
|
+
let buttonForeground = null;
|
|
101
|
+
let outlinedHover = null;
|
|
102
|
+
let outlinedPressed = null;
|
|
103
|
+
if (primaryBackground) {
|
|
104
|
+
var _valid$primaryForegro;
|
|
105
|
+
// Opposite directions: in a light theme mild is the paler wash and
|
|
106
|
+
// strong the deeper press state. These were once identical.
|
|
107
|
+
mildPrimary = valid.primaryBackgroundMild || shadedColour({
|
|
108
|
+
colour: primaryBackground,
|
|
109
|
+
isDarkTheme,
|
|
110
|
+
direction: 'forward',
|
|
33
111
|
intensity: 0.1
|
|
34
112
|
});
|
|
35
|
-
strongPrimary =
|
|
36
|
-
colour:
|
|
37
|
-
isDarkTheme
|
|
38
|
-
direction:
|
|
113
|
+
strongPrimary = valid.primaryBackgroundStrong || shadedColour({
|
|
114
|
+
colour: primaryBackground,
|
|
115
|
+
isDarkTheme,
|
|
116
|
+
direction: 'backward',
|
|
39
117
|
intensity: 0.1
|
|
40
118
|
});
|
|
119
|
+
|
|
120
|
+
// Honours an explicit value even when poor; only derives if absent.
|
|
121
|
+
buttonForeground = (_valid$primaryForegro = valid.primaryForeground) !== null && _valid$primaryForegro !== void 0 ? _valid$primaryForegro : onBrandColour(primaryBackground, theme);
|
|
122
|
+
|
|
123
|
+
// Stricter — a glyph failing 3:1 on the fill is invisible.
|
|
124
|
+
onBrand = resolveOnBrand(primaryBackground, theme, valid.primaryForeground);
|
|
125
|
+
|
|
126
|
+
// Pale tints behind an outlined button, hover the paler of the two.
|
|
127
|
+
outlinedHover = shadedColour({
|
|
128
|
+
colour: primaryBackground,
|
|
129
|
+
isDarkTheme,
|
|
130
|
+
direction: 'forward',
|
|
131
|
+
intensity: 0.5
|
|
132
|
+
});
|
|
133
|
+
outlinedPressed = shadedColour({
|
|
134
|
+
colour: primaryBackground,
|
|
135
|
+
isDarkTheme,
|
|
136
|
+
direction: 'forward',
|
|
137
|
+
intensity: 0.42
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
141
|
+
warnOnLowContrast(primaryBackground, 'primaryBackground', theme);
|
|
142
|
+
warnOnLowContrast(linkColor, 'linkColor', theme);
|
|
41
143
|
}
|
|
144
|
+
|
|
42
145
|
// slightly messy use of ts-expect-error but assignInlineVars only generates css vars to apply to a container
|
|
43
146
|
// any property that is undefined will not have an inline css var generated
|
|
44
147
|
return assignInlineVars(overdriveTokens, {
|
|
148
|
+
color: {
|
|
149
|
+
brand: {
|
|
150
|
+
//@ts-expect-error no undefined
|
|
151
|
+
solid: primaryBackground !== null && primaryBackground !== void 0 ? primaryBackground : undefined,
|
|
152
|
+
//@ts-expect-error no undefined
|
|
153
|
+
onSolid: (_onBrand = onBrand) !== null && _onBrand !== void 0 ? _onBrand : undefined
|
|
154
|
+
},
|
|
155
|
+
button: {
|
|
156
|
+
primary: {
|
|
157
|
+
outlined: {
|
|
158
|
+
// Verbatim — tenants expect their own brand.
|
|
159
|
+
//@ts-expect-error no undefined
|
|
160
|
+
border: primaryBackground !== null && primaryBackground !== void 0 ? primaryBackground : undefined,
|
|
161
|
+
//@ts-expect-error no undefined
|
|
162
|
+
text: primaryBackground !== null && primaryBackground !== void 0 ? primaryBackground : undefined,
|
|
163
|
+
//@ts-expect-error no undefined
|
|
164
|
+
hover: (_outlinedHover = outlinedHover) !== null && _outlinedHover !== void 0 ? _outlinedHover : undefined,
|
|
165
|
+
//@ts-expect-error no undefined
|
|
166
|
+
pressed: (_outlinedPressed = outlinedPressed) !== null && _outlinedPressed !== void 0 ? _outlinedPressed : undefined
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
45
171
|
colours: {
|
|
172
|
+
foreground: {
|
|
173
|
+
// also brands every focus ring, via focusOutline.css.ts
|
|
174
|
+
//@ts-expect-error no undefined
|
|
175
|
+
link: linkColor !== null && linkColor !== void 0 ? linkColor : undefined
|
|
176
|
+
},
|
|
46
177
|
intent: {
|
|
47
178
|
primary: {
|
|
48
179
|
background: {
|
|
49
180
|
//@ts-expect-error no undefined
|
|
50
|
-
standard:
|
|
181
|
+
standard: primaryBackground !== null && primaryBackground !== void 0 ? primaryBackground : undefined,
|
|
51
182
|
//@ts-expect-error no undefined
|
|
52
183
|
mild: (_mildPrimary = mildPrimary) !== null && _mildPrimary !== void 0 ? _mildPrimary : undefined,
|
|
53
184
|
//@ts-expect-error no undefined
|
|
54
185
|
strong: (_strongPrimary = strongPrimary) !== null && _strongPrimary !== void 0 ? _strongPrimary : undefined
|
|
55
186
|
},
|
|
187
|
+
// Derived — the theme's own value would leave a white
|
|
188
|
+
// label on a light brand.
|
|
56
189
|
//@ts-expect-error no undefined
|
|
57
|
-
foreground: (
|
|
190
|
+
foreground: (_buttonForeground = buttonForeground) !== null && _buttonForeground !== void 0 ? _buttonForeground : undefined,
|
|
58
191
|
//@ts-expect-error no undefined
|
|
59
|
-
border: (
|
|
192
|
+
border: (_valid$primaryBorder = valid.primaryBorder) !== null && _valid$primaryBorder !== void 0 ? _valid$primaryBorder : undefined
|
|
60
193
|
}
|
|
61
194
|
}
|
|
62
195
|
},
|
|
63
196
|
typography: {
|
|
64
197
|
colour: {
|
|
65
198
|
//@ts-expect-error no undefined
|
|
66
|
-
primary:
|
|
199
|
+
primary: primaryBackground !== null && primaryBackground !== void 0 ? primaryBackground : undefined,
|
|
200
|
+
// read by TextLink and by the `colour="link"` sprinkle
|
|
201
|
+
//@ts-expect-error no undefined
|
|
202
|
+
link: linkColor !== null && linkColor !== void 0 ? linkColor : undefined
|
|
67
203
|
}
|
|
68
204
|
}
|
|
69
205
|
});
|
|
70
|
-
}, [overrides,
|
|
206
|
+
}, [overrides, tokens]);
|
|
71
207
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useColorOverrides.spec.d.ts","sourceRoot":"","sources":["../../../lib/components/OverdriveProvider/useColorOverrides.spec.ts"],"names":[],"mappings":""}
|