@pathscale/ui 2.3.3 → 2.4.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/card/Card.css +14 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/layouts.manifest.json +1 -1
- package/dist/styles/glass.d.ts +89 -0
- package/dist/styles/glass.js +103 -0
- package/package.json +1 -1
|
@@ -98,16 +98,26 @@
|
|
|
98
98
|
backdrop-filter: none;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
/* Absorbs GlassPanel. The highlight ring was its `highlight` flag.
|
|
101
|
+
/* Absorbs GlassPanel. The highlight ring was its `highlight` flag.
|
|
102
|
+
|
|
103
|
+
Every `--glass-*` read below carries a fallback, and that is load-bearing
|
|
104
|
+
rather than tidy. An undefined custom property does not fall back to its
|
|
105
|
+
initial value: CSS drops the whole declaration. Three of these were read
|
|
106
|
+
bare, so a theme that defined twenty-eight of the thirty-one glass tokens
|
|
107
|
+
got a card with no background at all rather than a plainer one, and the
|
|
108
|
+
only themes that defined all thirty-one were the two shipped here. Both
|
|
109
|
+
use `white` for the three colours, so that is what the fallbacks say.
|
|
110
|
+
|
|
111
|
+
`src/styles/glass.ts` derives the other twenty-five from three numbers. */
|
|
102
112
|
.card--material-glass {
|
|
103
113
|
--card-bg: color-mix(
|
|
104
114
|
in oklab,
|
|
105
|
-
var(--glass-background-color),
|
|
115
|
+
var(--glass-background-color, white),
|
|
106
116
|
transparent calc(100% - var(--glass-background-opacity, 55%))
|
|
107
117
|
);
|
|
108
118
|
--card-border: color-mix(
|
|
109
119
|
in oklab,
|
|
110
|
-
var(--glass-border-color),
|
|
120
|
+
var(--glass-border-color, white),
|
|
111
121
|
transparent calc(100% - var(--glass-border-opacity, 12%))
|
|
112
122
|
);
|
|
113
123
|
backdrop-filter: blur(var(--card-glass-blur, var(--glass-blur, 50px)))
|
|
@@ -125,7 +135,7 @@
|
|
|
125
135
|
box-shadow: inset 0 var(--border, 1px) 0 0
|
|
126
136
|
color-mix(
|
|
127
137
|
in oklab,
|
|
128
|
-
var(--glass-highlight-color),
|
|
138
|
+
var(--glass-highlight-color, white),
|
|
129
139
|
transparent calc(100% - var(--glass-highlight-opacity, 18%))
|
|
130
140
|
);
|
|
131
141
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -130,3 +130,5 @@ export type { ColorSwatchProps, ColorSwatchShape, ColorSwatchSize, } from "./com
|
|
|
130
130
|
export { default as ChatBubble } from "./components/chatbubble";
|
|
131
131
|
export { summarizeStatus, diffStatus } from "./components/status";
|
|
132
132
|
export type { Health, Quality, StatusItem, StatusSummary, StatusTransition } from "./components/status";
|
|
133
|
+
export { GLASS_DEFAULTS, GLASS_LIMITS, applyGlassTokens, glassTokensToCss, resolveGlassTokens, } from "./styles/glass";
|
|
134
|
+
export type { GlassMode, GlassTuning } from "./styles/glass";
|
package/dist/index.js
CHANGED
|
@@ -73,4 +73,5 @@ export { ListBoxItem, ListBoxItemIndicator, ListBoxSection, default as ListBox }
|
|
|
73
73
|
export { default as ColorSwatch } from "./components/color-swatch/index.js";
|
|
74
74
|
export { default as ChatBubble } from "./components/chatbubble/index.js";
|
|
75
75
|
export { diffStatus, summarizeStatus } from "./components/status/index.js";
|
|
76
|
+
export { GLASS_DEFAULTS, GLASS_LIMITS, applyGlassTokens, glassTokensToCss, resolveGlassTokens } from "./styles/glass.js";
|
|
76
77
|
export { DEFAULT_GAP as DEFAULT_TOAST_GAP, DEFAULT_MAX_VISIBLE_TOAST, DEFAULT_SCALE_FACTOR as DEFAULT_TOAST_SCALE_FACTOR, DEFAULT_TOAST_TIMEOUT, DEFAULT_TOAST_WIDTH, ToastActionButton, ToastCloseButton, ToastContent, ToastDescription, ToastIndicator, ToastProvider, ToastQueue, ToastTitle, index_js_toast as Toast, index_js_toast as toast, toastQueue };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Glass, as three numbers instead of thirty-one.
|
|
3
|
+
*
|
|
4
|
+
* `material="glass"` is styled by a family of `--glass-*` custom properties.
|
|
5
|
+
* Both shipped themes declare all of them by hand, which made glass a thing you
|
|
6
|
+
* inherited rather than a thing you could add: a new theme had to copy
|
|
7
|
+
* thirty-one values, and three of them are read without a fallback, so a theme
|
|
8
|
+
* that copied twenty-eight got a card with no background at all rather than a
|
|
9
|
+
* plainer one. An undefined custom property does not fall back to its initial
|
|
10
|
+
* value; CSS drops the whole declaration.
|
|
11
|
+
*
|
|
12
|
+
* So the set splits in two. Six are colours and stay with the theme, because
|
|
13
|
+
* only the theme knows what its glass is tinted with. The other twenty-five are
|
|
14
|
+
* opacities, sizes and blurs, and every one of them is a function of three
|
|
15
|
+
* numbers:
|
|
16
|
+
*
|
|
17
|
+
* blur how far the backdrop is smeared, in pixels
|
|
18
|
+
* refraction how much the surface asserts itself: tint, border, highlights
|
|
19
|
+
* depth how far off the page it sits: glows, sheen, shadow
|
|
20
|
+
*
|
|
21
|
+
* Adding glass to a theme is now those three numbers and, if it wants them, the
|
|
22
|
+
* six colours. The curves are lifted from the tuning surface that consulting.parcle.ai
|
|
23
|
+
* arrived at by eye against this same token vocabulary, so the shipped themes
|
|
24
|
+
* keep the appearance they already had.
|
|
25
|
+
*/
|
|
26
|
+
export type GlassMode = "light" | "dark";
|
|
27
|
+
/** What a theme sets. Everything else is derived. */
|
|
28
|
+
export type GlassTuning = {
|
|
29
|
+
/** Backdrop blur radius in pixels. 0 turns glass into a plain translucent fill. */
|
|
30
|
+
blur: number;
|
|
31
|
+
/**
|
|
32
|
+
* How much the surface asserts itself, 0 to 0.4.
|
|
33
|
+
*
|
|
34
|
+
* Drives tint, border, highlights and rim together, because they are one
|
|
35
|
+
* physical property and tuning them separately is how the thirty-one-value
|
|
36
|
+
* version became unmaintainable.
|
|
37
|
+
*/
|
|
38
|
+
refraction: number;
|
|
39
|
+
/** How far off the page it sits, 0 to 30. Drives glows, sheen and shadow. */
|
|
40
|
+
depth: number;
|
|
41
|
+
};
|
|
42
|
+
export declare const GLASS_LIMITS: {
|
|
43
|
+
readonly blur: {
|
|
44
|
+
readonly min: 0;
|
|
45
|
+
readonly max: 50;
|
|
46
|
+
};
|
|
47
|
+
readonly refraction: {
|
|
48
|
+
readonly min: 0;
|
|
49
|
+
readonly max: 0.4;
|
|
50
|
+
};
|
|
51
|
+
readonly depth: {
|
|
52
|
+
readonly min: 0;
|
|
53
|
+
readonly max: 30;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/** What the shipped themes use. Both land on the same numbers. */
|
|
57
|
+
export declare const GLASS_DEFAULTS: Record<GlassMode, GlassTuning>;
|
|
58
|
+
/**
|
|
59
|
+
* The `--glass-*` custom properties three numbers imply.
|
|
60
|
+
*
|
|
61
|
+
* Returns only what is derived. The six colours - background, border,
|
|
62
|
+
* highlight, the two rim stops and the inner glow - are the theme's, and a
|
|
63
|
+
* theme that sets none of them still renders because the component CSS carries
|
|
64
|
+
* fallbacks for all six.
|
|
65
|
+
*/
|
|
66
|
+
export declare function resolveGlassTokens(tuning: Partial<GlassTuning>, mode: GlassMode): Record<string, string>;
|
|
67
|
+
/**
|
|
68
|
+
* Writes the derived tokens onto an element, `:root` by default.
|
|
69
|
+
*
|
|
70
|
+
* Inline styles rather than a stylesheet, because this is the layer above the
|
|
71
|
+
* theme: a theme sets its glass in CSS, and this is for changing it at runtime
|
|
72
|
+
* without a rebuild - a settings panel, a per-route override, a preview.
|
|
73
|
+
*
|
|
74
|
+
* A no-op without a DOM, so it is safe to call during server rendering.
|
|
75
|
+
*/
|
|
76
|
+
export declare function applyGlassTokens(tuning: Partial<GlassTuning>, mode: GlassMode, target?: {
|
|
77
|
+
style: {
|
|
78
|
+
setProperty(name: string, value: string): void;
|
|
79
|
+
};
|
|
80
|
+
}): void;
|
|
81
|
+
/**
|
|
82
|
+
* The derived tokens as a CSS declaration block, for a theme that wants them
|
|
83
|
+
* baked in rather than applied at runtime.
|
|
84
|
+
*
|
|
85
|
+
* The intended use is a build step or a scratch buffer: paste the output into a
|
|
86
|
+
* theme file beside its six colours and glass is part of that theme, with no
|
|
87
|
+
* JavaScript involved.
|
|
88
|
+
*/
|
|
89
|
+
export declare function glassTokensToCss(tuning: Partial<GlassTuning>, mode: GlassMode): string;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const GLASS_LIMITS = {
|
|
2
|
+
blur: {
|
|
3
|
+
min: 0,
|
|
4
|
+
max: 50
|
|
5
|
+
},
|
|
6
|
+
refraction: {
|
|
7
|
+
min: 0,
|
|
8
|
+
max: 0.4
|
|
9
|
+
},
|
|
10
|
+
depth: {
|
|
11
|
+
min: 0,
|
|
12
|
+
max: 30
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const GLASS_DEFAULTS = {
|
|
16
|
+
light: {
|
|
17
|
+
blur: 9,
|
|
18
|
+
refraction: 0.31,
|
|
19
|
+
depth: 24
|
|
20
|
+
},
|
|
21
|
+
dark: {
|
|
22
|
+
blur: 9,
|
|
23
|
+
refraction: 0.31,
|
|
24
|
+
depth: 24
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const clamp = (value, min, max, fallback)=>{
|
|
28
|
+
const n = Number(value);
|
|
29
|
+
return Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : fallback;
|
|
30
|
+
};
|
|
31
|
+
const round = (v, places = 2)=>String(Math.round((v + Number.EPSILON) * 10 ** places) / 10 ** places);
|
|
32
|
+
const pct = (v, places = 2)=>`${round(v, places)}%`;
|
|
33
|
+
const px = (v, places = 2)=>`${round(v, places)}px`;
|
|
34
|
+
function normalise(tuning, mode) {
|
|
35
|
+
const base = GLASS_DEFAULTS[mode];
|
|
36
|
+
const blur = clamp(tuning.blur, GLASS_LIMITS.blur.min, GLASS_LIMITS.blur.max, base.blur);
|
|
37
|
+
const refraction = clamp(tuning.refraction, GLASS_LIMITS.refraction.min, GLASS_LIMITS.refraction.max, base.refraction);
|
|
38
|
+
const depth = clamp(tuning.depth, GLASS_LIMITS.depth.min, GLASS_LIMITS.depth.max, base.depth);
|
|
39
|
+
const r = refraction / GLASS_LIMITS.refraction.max;
|
|
40
|
+
const d = depth / GLASS_LIMITS.depth.max;
|
|
41
|
+
return {
|
|
42
|
+
blur,
|
|
43
|
+
light: "light" === mode,
|
|
44
|
+
rs: 0 === r ? 0 : r ** 0.82,
|
|
45
|
+
rv: 0 === r ? 0 : r ** 0.95,
|
|
46
|
+
ds: 0 === d ? 0 : d ** 0.85,
|
|
47
|
+
r,
|
|
48
|
+
d
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function resolveGlassTokens(tuning, mode) {
|
|
52
|
+
const v = normalise(tuning, mode);
|
|
53
|
+
const { rs, rv, ds, light } = v;
|
|
54
|
+
const zero = 0 === v.r;
|
|
55
|
+
const background = light ? zero ? 0 : 18 + 30 * rv : 7 * rv;
|
|
56
|
+
const border = light ? zero ? 0 : 18 + 18 * rs : 26 * rs;
|
|
57
|
+
const highlight = light ? zero ? 0 : 22 + 26 * rs : 24 * rs;
|
|
58
|
+
const bottomHighlight = light ? zero ? 0 : 10 + 14 * rs + 5 * ds : 3.5 * rs + 3 * rs * ds;
|
|
59
|
+
const edgeHighlight = light ? zero ? 0 : 20 + 22 * rs + 4 * ds : 18 * rs + 4 * ds;
|
|
60
|
+
const rimStart = light ? zero ? 0 : 14 + 18 * rs + 4 * ds : 17 * rs + 3 * ds;
|
|
61
|
+
const rimEnd = light ? zero ? 0 : 18 + 22 * rs + 4 * ds : 23 * rs + 5 * ds;
|
|
62
|
+
const innerGlow = light ? 0.035 * rs + 0.045 * rs * ds + 0.012 * ds : 0.055 * rs * ds + 0.018 * ds;
|
|
63
|
+
const topGlow = light ? 8 * ds * (0.4 + 0.6 * rs) : 6 * ds * (0.35 + 0.65 * rs);
|
|
64
|
+
const bottomGlow = light ? 9 * ds * (0.25 + 0.65 * rs) : 5 * ds * (0.2 + 0.55 * rs);
|
|
65
|
+
const sheen = light ? 14 * ds * (0.25 + 0.75 * rs) : 10 * ds * (0.25 + 0.75 * rs);
|
|
66
|
+
const fallbackBackground = Math.min(70, light ? background + 10 * rs : 8 * background + 12 * rs);
|
|
67
|
+
const shadow = ds > 0 ? `0 ${px(light ? 5 + 10 * ds : 4 + 10 * ds)} ${px(light ? 20 + 28 * ds : 18 + 26 * ds)} rgb(0 0 0 / ${pct(light ? 2 + 5 * ds : 3 + 7 * ds)})` : "0 0 0 rgb(0 0 0 / 0%)";
|
|
68
|
+
return {
|
|
69
|
+
"--glass-blur": px(v.blur, 0),
|
|
70
|
+
"--glass-saturation": round(1 + 0.18 * rs),
|
|
71
|
+
"--glass-brightness": "1",
|
|
72
|
+
"--glass-background-opacity": pct(background),
|
|
73
|
+
"--glass-border-opacity": pct(border),
|
|
74
|
+
"--glass-highlight-opacity": pct(highlight),
|
|
75
|
+
"--glass-bottom-highlight-opacity": pct(bottomHighlight),
|
|
76
|
+
"--glass-edge-highlight-opacity": pct(edgeHighlight),
|
|
77
|
+
"--glass-rim-start-opacity": pct(rimStart),
|
|
78
|
+
"--glass-rim-end-opacity": pct(rimEnd),
|
|
79
|
+
"--glass-inner-glow-alpha": round(innerGlow, 3),
|
|
80
|
+
"--glass-inner-glow-blur": px(ds > 0 ? 1 + 3 * ds : 0),
|
|
81
|
+
"--glass-inner-glow-spread": "0px",
|
|
82
|
+
"--glass-depth-top-glow-opacity": pct(topGlow),
|
|
83
|
+
"--glass-depth-bottom-glow-opacity": pct(bottomGlow),
|
|
84
|
+
"--glass-depth-sheen-opacity": pct(sheen),
|
|
85
|
+
"--glass-depth-sheen-size": pct(82 - 16 * ds),
|
|
86
|
+
"--glass-depth-surface-opacity": "0%",
|
|
87
|
+
"--glass-depth-surface-size": pct(82),
|
|
88
|
+
"--glass-glow-ring-opacity": pct(light ? 6 * rs : 10 * rs),
|
|
89
|
+
"--glass-liquid-edge-size": px(1 + 2 * rs),
|
|
90
|
+
"--glass-liquid-inner-blur": px(6 + 12 * rs),
|
|
91
|
+
"--glass-shadow-depth": shadow,
|
|
92
|
+
"--glass-fallback-background-opacity": pct(fallbackBackground)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function applyGlassTokens(tuning, mode, target) {
|
|
96
|
+
const element = target ?? ("u" < typeof document ? void 0 : document.documentElement);
|
|
97
|
+
if (!element) return;
|
|
98
|
+
for (const [name, value] of Object.entries(resolveGlassTokens(tuning, mode)))element.style.setProperty(name, value);
|
|
99
|
+
}
|
|
100
|
+
function glassTokensToCss(tuning, mode) {
|
|
101
|
+
return Object.entries(resolveGlassTokens(tuning, mode)).map(([name, value])=>` ${name}: ${value};`).join("\n");
|
|
102
|
+
}
|
|
103
|
+
export { GLASS_DEFAULTS, GLASS_LIMITS, applyGlassTokens, glassTokensToCss, resolveGlassTokens };
|