actual-css 0.14.0 → 0.15.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/CHANGELOG.md +56 -0
- package/README.md +8 -8
- package/components.json +51 -6
- package/dist/actual.full.css +367 -31
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/docs/design-notes/widget-primitives.md +4 -0
- package/docs/navigation.json +4 -1
- package/docs/pages/components/accordion.md +15 -18
- package/docs/pages/components/avatar.md +1 -0
- package/docs/pages/components/badge.md +41 -5
- package/docs/pages/components/button.md +5 -0
- package/docs/pages/components/card.md +34 -0
- package/docs/pages/components/diagrams.md +96 -0
- package/docs/pages/components/steps.md +1 -1
- package/docs/pages/components/table.md +4 -0
- package/docs/pages/components/timeline.md +111 -0
- package/docs/pages/enhancements/flyout.md +4 -3
- package/docs/pages/enhancements/overview.md +2 -1
- package/docs/pages/enhancements/tabs.md +48 -6
- package/docs/pages/enhancements/tooltip.md +3 -1
- package/docs/pages/examples/overview.md +5 -2
- package/docs/pages/forms/choice-cards.md +3 -0
- package/docs/pages/forms/combobox.md +34 -19
- package/docs/pages/forms/controls.md +2 -0
- package/docs/pages/forms/date-picker.md +34 -13
- package/docs/pages/forms/file-upload.md +120 -0
- package/docs/pages/forms/overview.md +8 -0
- package/docs/pages/foundations/philosophy.md +6 -0
- package/docs/pages/foundations/theming.md +57 -5
- package/docs/pages/foundations/typography.md +3 -0
- package/docs/pages/guides/introduction.md +1 -1
- package/docs/pages/guides/modular-import.md +124 -0
- package/docs/pages/guides/upgrading.md +63 -0
- package/package.json +4 -3
- package/reserved-classes.json +3 -0
- package/src/css/components/accordion.css +7 -3
- package/src/css/components/alert.css +9 -1
- package/src/css/components/badge.css +38 -11
- package/src/css/components/button.css +10 -2
- package/src/css/components/card.css +9 -0
- package/src/css/components/index.css +1 -0
- package/src/css/components/skeleton.css +11 -0
- package/src/css/components/tab.css +77 -0
- package/src/css/components/table.css +7 -1
- package/src/css/components/timeline.css +160 -0
- package/src/css/core/base.css +3 -1
- package/src/css/core/theme.css +6 -1
- package/src/css/core/tokens.css +3 -3
- package/src/css/forms/choice-card.css +5 -2
- package/src/css/forms/color-swatch.css +4 -0
- package/src/css/forms/control.css +12 -3
- package/src/css/forms/custom-select.css +1 -1
- package/src/css/typography/prose.css +4 -2
- package/src/js/enhance.js +14 -0
- package/src/js/floating-space.js +26 -0
- package/src/js/flyout.js +3 -1
- package/src/js/parse-config.js +5 -2
- package/src/js/tooltip.js +2 -2
- package/src/tooling/design-tokens.js +2 -0
- package/src/tooling/theme-contrast.js +1 -1
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
--control-bg: var(--surface-raised);
|
|
39
39
|
outline: var(--focus-ring-width) solid var(--form-invalid-border, var(--focus));
|
|
40
40
|
outline-offset: calc(var(--focus-ring-width) * -1);
|
|
41
|
-
box-shadow: none;
|
|
41
|
+
box-shadow: var(--control-shadow, none);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
&::picker-icon {
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
/* --link is a theme-level token (core/base.css also reads it for bare links);
|
|
89
89
|
prose falls back to --primary so a theme that never sets it is unaffected. */
|
|
90
90
|
.prose :where(a) {
|
|
91
|
-
color: var(--link, var(--primary));
|
|
91
|
+
color: var(--surface-link, var(--link, var(--primary)));
|
|
92
92
|
text-decoration-line: underline;
|
|
93
93
|
text-decoration-thickness: 0.08em;
|
|
94
94
|
text-underline-offset: 0.18em;
|
|
@@ -100,7 +100,9 @@
|
|
|
100
100
|
|
|
101
101
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
102
102
|
.prose :where(a:hover, a:focus-visible) {
|
|
103
|
-
|
|
103
|
+
/* A solid surface owns its contrast pair in every state; mixing in the
|
|
104
|
+
page's --text would pull its links toward the wrong background. */
|
|
105
|
+
color: var(--surface-link, color-mix(in oklab, var(--link, var(--primary)), var(--text) 15%));
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
package/src/js/enhance.js
CHANGED
|
@@ -31,6 +31,20 @@
|
|
|
31
31
|
const registries = new WeakMap();
|
|
32
32
|
const ownedNames = new WeakMap();
|
|
33
33
|
|
|
34
|
+
// Each evaluation owns its registries, so a second copy (the dist bundle plus
|
|
35
|
+
// source modules, or two bundles) registers every behavior twice and fails
|
|
36
|
+
// silently — a flyout opens then closes. Every built-in imports this module,
|
|
37
|
+
// so the marker catches any duplicated runtime once, here.
|
|
38
|
+
const RUNTIME = Symbol.for("actual-css.runtime");
|
|
39
|
+
if (typeof document !== "undefined") {
|
|
40
|
+
if (globalThis[RUNTIME]) {
|
|
41
|
+
console.warn(
|
|
42
|
+
"actual-css: a second copy of the JavaScript runtime is loaded. Load the full bundle or the source modules, never both.",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
globalThis[RUNTIME] = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
// Node type constants as literals, not the realm's Node global, so nodes from
|
|
35
49
|
// another document/window compare correctly.
|
|
36
50
|
const ELEMENT_NODE = 1;
|
package/src/js/floating-space.js
CHANGED
|
@@ -29,6 +29,32 @@ function isViewportAnchored(anchor) {
|
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// Mirrors the placements @lekoala/floating accepts; it throws on any other
|
|
33
|
+
// value, and from an autoUpdate callback that throw would repeat on every
|
|
34
|
+
// scroll. Markup is validated here instead, so a typo warns once.
|
|
35
|
+
const PLACEMENTS = new Set(
|
|
36
|
+
["top", "bottom", "left", "right"].flatMap((side) => [side, `${side}-start`, `${side}-end`]),
|
|
37
|
+
);
|
|
38
|
+
const warnedPlacements = new WeakSet();
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The author's placement attribute, or null when absent or unknown.
|
|
42
|
+
*
|
|
43
|
+
* @param {Element | null | undefined} el
|
|
44
|
+
* @param {string} attribute
|
|
45
|
+
* @returns {string | null}
|
|
46
|
+
*/
|
|
47
|
+
export function readPlacement(el, attribute) {
|
|
48
|
+
const value = el?.getAttribute(attribute);
|
|
49
|
+
if (!value) return null;
|
|
50
|
+
if (PLACEMENTS.has(value)) return value;
|
|
51
|
+
if (!warnedPlacements.has(el)) {
|
|
52
|
+
warnedPlacements.add(el);
|
|
53
|
+
console.warn(`Unknown ${attribute}="${value}" ignored`, el);
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
/**
|
|
33
59
|
* @param {Element | null | undefined} anchor
|
|
34
60
|
* @returns {{ space: "viewport" | "document", position: "fixed" | "absolute" }}
|
package/src/js/flyout.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { registerEnhancement } from "./enhance.js";
|
|
2
|
+
import { readPlacement } from "./floating-space.js";
|
|
2
3
|
import { focusFirstDescendant } from "./focus.js";
|
|
3
4
|
import { shouldIgnoreKey } from "./keys.js";
|
|
4
5
|
import { connectMenu, focusFirstMenuItem, focusLastMenuItem } from "./menu.js";
|
|
@@ -9,7 +10,8 @@ const triggerMap = new WeakMap();
|
|
|
9
10
|
function readFlyoutOptions(panel) {
|
|
10
11
|
const opts = { autoClose: "true" };
|
|
11
12
|
const ds = panel.dataset;
|
|
12
|
-
|
|
13
|
+
const placement = readPlacement(panel, "data-flyout-placement");
|
|
14
|
+
if (placement) opts.placement = placement;
|
|
13
15
|
if (ds.flyoutDistance != null) {
|
|
14
16
|
const d = Number.parseFloat(ds.flyoutDistance);
|
|
15
17
|
if (Number.isFinite(d)) opts.distance = d;
|
package/src/js/parse-config.js
CHANGED
|
@@ -11,10 +11,13 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
function relax(source) {
|
|
14
|
+
// Double-quoted strings are matched first and copied verbatim, so text
|
|
15
|
+
// such as `http:` inside them is never mistaken for an unquoted key.
|
|
14
16
|
return source.replace(
|
|
15
|
-
/([a-zA-Z_$][\w$-]*)\s*:|'((?:\\'|[^'])*)'/g,
|
|
16
|
-
(
|
|
17
|
+
/"(?:\\.|[^"\\])*"|([a-zA-Z_$][\w$-]*)\s*:|'((?:\\'|[^'])*)'/g,
|
|
18
|
+
(match, key, stringContent) => {
|
|
17
19
|
if (key) return `"${key}":`;
|
|
20
|
+
if (stringContent === undefined) return match;
|
|
18
21
|
const unescaped = stringContent.replace(/\\'/g, "'");
|
|
19
22
|
const escaped = unescaped.replace(/"/g, '\\"');
|
|
20
23
|
return `"${escaped}"`;
|
package/src/js/tooltip.js
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
import { autoUpdate, reposition } from "@lekoala/floating";
|
|
52
52
|
import enhance from "./enhance.js";
|
|
53
53
|
import { registerEscapeDismissal } from "./escape.js";
|
|
54
|
-
import { positionModeFor } from "./floating-space.js";
|
|
54
|
+
import { positionModeFor, readPlacement } from "./floating-space.js";
|
|
55
55
|
import { CLASSES } from "./selectors.js";
|
|
56
56
|
|
|
57
57
|
const SHOW_DELAY_MS = 150;
|
|
@@ -144,7 +144,7 @@ export function isTooltipVisible(tip) {
|
|
|
144
144
|
* the tip's own placement never enters into it.
|
|
145
145
|
*/
|
|
146
146
|
function placementFor(ref) {
|
|
147
|
-
return ref
|
|
147
|
+
return readPlacement(ref, "data-tooltip-placement") ?? "top";
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
function hasOption(trigger, name) {
|
|
@@ -44,6 +44,7 @@ export const THEME_COLORS = [
|
|
|
44
44
|
"heading",
|
|
45
45
|
"border",
|
|
46
46
|
"border-control",
|
|
47
|
+
"control-default-bg",
|
|
47
48
|
"focus",
|
|
48
49
|
"hover-overlay",
|
|
49
50
|
"hover-overlay-solid",
|
|
@@ -101,6 +102,7 @@ export const FOUNDATIONS = {
|
|
|
101
102
|
listed here (tests/design-tokens.test.js), so a new token cannot silently
|
|
102
103
|
stay out of the design tools. */
|
|
103
104
|
export const NOT_EXPORTED = {
|
|
105
|
+
"internal surface context, not a palette color": ["surface-link"],
|
|
104
106
|
"internal 0/1 weights selecting a control step; the steps are exported": [
|
|
105
107
|
"control-step-sm",
|
|
106
108
|
"control-step-md",
|
|
@@ -37,7 +37,7 @@ export const INTENTS = ["primary", "secondary", "success", "warning", "danger",
|
|
|
37
37
|
export const SURFACES = ["surface", "surface-raised", "surface-subtle"];
|
|
38
38
|
|
|
39
39
|
/* Badges state .soft explicitly: a theme may fill badges by default
|
|
40
|
-
|
|
40
|
+
by a local rule, which would measure a solid pair against the soft hover.
|
|
41
41
|
The theme name is read from a file by a regex, so it never enters this
|
|
42
42
|
markup: measureContrast() sets it through dataset. `scheme` is only ever
|
|
43
43
|
"light" or "dark". */
|