@ds-mo/ui 1.6.0 → 1.6.1
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/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1782185018864
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ds-mo/ui",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "CompoMo — composable web components styled with TokoMo design tokens",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
"types": "./src/wc/nav/index.ts",
|
|
46
46
|
"import": "./src/wc/nav/index.ts"
|
|
47
47
|
},
|
|
48
|
+
"./utils": {
|
|
49
|
+
"types": "./src/wc/utils/index.ts",
|
|
50
|
+
"import": "./src/wc/utils/index.ts"
|
|
51
|
+
},
|
|
48
52
|
"./dist/components/*": "./dist/components/*"
|
|
49
53
|
},
|
|
50
54
|
"files": [
|
|
@@ -55,6 +59,7 @@
|
|
|
55
59
|
"!src/wc/components/**/*.stories.ts",
|
|
56
60
|
"!src/wc/components/**/*.stories.tsx",
|
|
57
61
|
"src/wc/nav",
|
|
62
|
+
"src/wc/utils",
|
|
58
63
|
"src/angular",
|
|
59
64
|
"src/react"
|
|
60
65
|
],
|
|
@@ -63,6 +68,7 @@
|
|
|
63
68
|
"pretypecheck": "node scripts/generate-icon-catalog.mjs",
|
|
64
69
|
"pretest": "node scripts/generate-icon-catalog.mjs",
|
|
65
70
|
"build": "stencil build && node scripts/patch-index-types.mjs && node scripts/verify-icons-externalized.mjs && node scripts/write-build-stamp.mjs",
|
|
71
|
+
"verify:pack": "node scripts/verify-npm-pack.mjs && node scripts/verify-nav-import.mjs",
|
|
66
72
|
"test": "node --import tsx/esm --test tests/panel-nav-utils.test.ts tests/shell-view-transition.test.ts tests/shell-gradient.test.ts tests/resolve-css-length-px.test.ts tests/resolve-css-time-ms.test.ts tests/overlay-positioning.test.ts tests/bar-nav-utils.test.ts tests/bar-nav-tabs-menu-utils.test.ts tests/bar-nav-dom-utils.test.ts tests/icon-catalog.test.ts",
|
|
67
73
|
"test:e2e": "npm run build && playwright test",
|
|
68
74
|
"test:e2e:install": "playwright install chromium",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const lengthPxCache = new Map<string, number>();
|
|
2
|
+
|
|
3
|
+
let probeEl: HTMLElement | null = null;
|
|
4
|
+
|
|
5
|
+
function getProbeElement(): HTMLElement | null {
|
|
6
|
+
if (typeof document === 'undefined') return null;
|
|
7
|
+
|
|
8
|
+
if (!probeEl) {
|
|
9
|
+
probeEl = document.createElement('div');
|
|
10
|
+
probeEl.setAttribute('aria-hidden', 'true');
|
|
11
|
+
probeEl.style.cssText =
|
|
12
|
+
'position:absolute;visibility:hidden;pointer-events:none;top:0;left:0;width:0;height:0;overflow:hidden;';
|
|
13
|
+
document.documentElement.appendChild(probeEl);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return probeEl;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Clear session cache (tests only). */
|
|
20
|
+
export function clearCssLengthPxCache(): void {
|
|
21
|
+
lengthPxCache.clear();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a CSS length to pixels for layout math.
|
|
26
|
+
* Numbers pass through; `var(--dimension-*)`, `calc(...)`, and `16px` resolve via a hidden probe.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveCssLengthPx(
|
|
29
|
+
value: number | string | undefined,
|
|
30
|
+
fallback: number | string,
|
|
31
|
+
): number {
|
|
32
|
+
const resolved = value === undefined || value === null || value === '' ? fallback : value;
|
|
33
|
+
if (typeof resolved === 'number') return resolved;
|
|
34
|
+
|
|
35
|
+
const trimmed = resolved.trim();
|
|
36
|
+
if (!trimmed) return resolveCssLengthPx(fallback, 0);
|
|
37
|
+
|
|
38
|
+
const cached = lengthPxCache.get(trimmed);
|
|
39
|
+
if (cached !== undefined) return cached;
|
|
40
|
+
|
|
41
|
+
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
42
|
+
const n = Number(trimmed);
|
|
43
|
+
lengthPxCache.set(trimmed, n);
|
|
44
|
+
return n;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const pxMatch = trimmed.match(/^(-?\d+(\.\d+)?)px$/);
|
|
48
|
+
if (pxMatch) {
|
|
49
|
+
const px = parseFloat(pxMatch[1]);
|
|
50
|
+
lengthPxCache.set(trimmed, px);
|
|
51
|
+
return px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const probe = getProbeElement();
|
|
55
|
+
if (!probe) {
|
|
56
|
+
return typeof fallback === 'number' ? fallback : 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
probe.style.width = trimmed;
|
|
60
|
+
const px = probe.getBoundingClientRect().width;
|
|
61
|
+
probe.style.width = '';
|
|
62
|
+
lengthPxCache.set(trimmed, px);
|
|
63
|
+
return px;
|
|
64
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Parse a CSS <time> value (or motion shorthand's first token) to milliseconds. */
|
|
2
|
+
export function parseCssTimeMs(value: string, fallback: number): number {
|
|
3
|
+
const firstToken = value.trim().split(/\s+/)[0] ?? '';
|
|
4
|
+
const num = parseFloat(firstToken);
|
|
5
|
+
if (Number.isNaN(num)) return fallback;
|
|
6
|
+
if (/ms\s*$/.test(firstToken)) return num;
|
|
7
|
+
if (/s\s*$/.test(firstToken)) return num * 1000;
|
|
8
|
+
return num;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function extractCssCustomProp(ref: string): string | null {
|
|
12
|
+
const varMatch = ref.match(/^var\(\s*(--[^),]+)/);
|
|
13
|
+
if (varMatch) return varMatch[1].trim();
|
|
14
|
+
if (ref.startsWith('--')) return ref.trim();
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function readTokenTimeMs(token: string, fallback: number): number {
|
|
19
|
+
if (typeof document === 'undefined') return fallback;
|
|
20
|
+
|
|
21
|
+
const prop = extractCssCustomProp(token);
|
|
22
|
+
if (!prop) return parseCssTimeMs(token, fallback);
|
|
23
|
+
|
|
24
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue(prop).trim();
|
|
25
|
+
return parseCssTimeMs(raw, fallback);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a duration to milliseconds for JS timers aligned with CSS motion tokens.
|
|
30
|
+
* Accepts numbers (ms), raw times (`200ms`, `0.75s`), or `var(--effect-*)` references.
|
|
31
|
+
*/
|
|
32
|
+
export function resolveCssTimeMs(
|
|
33
|
+
value: number | string | undefined,
|
|
34
|
+
fallbackToken: string,
|
|
35
|
+
): number {
|
|
36
|
+
if (typeof value === 'number') return value;
|
|
37
|
+
|
|
38
|
+
const token = typeof value === 'string' && value.trim() ? value.trim() : fallbackToken;
|
|
39
|
+
const prop = extractCssCustomProp(token);
|
|
40
|
+
|
|
41
|
+
if (prop) {
|
|
42
|
+
return readTokenTimeMs(token, readTokenTimeMs(fallbackToken, 200));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return parseCssTimeMs(token, readTokenTimeMs(fallbackToken, 200));
|
|
46
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dimensionIconographyMd,
|
|
3
|
+
dimensionIconographySm,
|
|
4
|
+
dimensionIconographyXs,
|
|
5
|
+
dimensionMenuWidthXs,
|
|
6
|
+
dimensionPanelWidth2xs,
|
|
7
|
+
dimensionPanelWidthLg,
|
|
8
|
+
dimensionPanelWidthMd,
|
|
9
|
+
dimensionSize300,
|
|
10
|
+
dimensionSize600,
|
|
11
|
+
dimensionSize800,
|
|
12
|
+
dimensionSpace050,
|
|
13
|
+
dimensionSpace200,
|
|
14
|
+
effectAnimationDelayLong2,
|
|
15
|
+
effectAnimationDelayMedium1,
|
|
16
|
+
effectAnimationDelayShort2,
|
|
17
|
+
effectAnimationDurationMedium1,
|
|
18
|
+
effectAnimationDurationShort3,
|
|
19
|
+
effectMotionShort3,
|
|
20
|
+
} from '@ds-mo/tokens/ts';
|
|
21
|
+
|
|
22
|
+
/** TokoMo CSS custom-property names for shared component defaults (runtime resolution). */
|
|
23
|
+
export const TOKEN_DEFAULTS = {
|
|
24
|
+
space050: dimensionSpace050,
|
|
25
|
+
space200: dimensionSpace200,
|
|
26
|
+
size300: dimensionSize300,
|
|
27
|
+
size600: dimensionSize600,
|
|
28
|
+
size800: dimensionSize800,
|
|
29
|
+
iconographyMd: dimensionIconographyMd,
|
|
30
|
+
iconographySm: dimensionIconographySm,
|
|
31
|
+
iconographyXs: dimensionIconographyXs,
|
|
32
|
+
panelWidth2xs: dimensionPanelWidth2xs,
|
|
33
|
+
panelWidthMd: dimensionPanelWidthMd,
|
|
34
|
+
panelWidthLg: dimensionPanelWidthLg,
|
|
35
|
+
menuWidthXs: dimensionMenuWidthXs,
|
|
36
|
+
motionShort3: effectMotionShort3,
|
|
37
|
+
animationDurationShort3: effectAnimationDurationShort3,
|
|
38
|
+
animationDurationMedium1: effectAnimationDurationMedium1,
|
|
39
|
+
animationDelayMedium1: effectAnimationDelayMedium1,
|
|
40
|
+
animationDelayShort2: effectAnimationDelayShort2,
|
|
41
|
+
animationDelayLong2: effectAnimationDelayLong2,
|
|
42
|
+
/** Unmeasured menu height fallback: 20× base (160px at default scale). */
|
|
43
|
+
menuFallbackHeight: 'calc(var(--dimension-size-base) * 20)',
|
|
44
|
+
/** Unmeasured tooltip width fallback: size-800 + size-200 (80px). */
|
|
45
|
+
tooltipFallbackWidth: 'calc(var(--dimension-size-800) + var(--dimension-size-200))',
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
export type TokenDefaultKey = keyof typeof TOKEN_DEFAULTS;
|