@pieai/swimmer-ui-kit 1.1.0 → 1.2.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 +30 -0
- package/bin/swimmer-ui-check.mjs +26 -11
- package/dist/index.d.ts +60 -12
- package/dist/index.js +4729 -3115
- package/dist/preview.css +1 -1
- package/dist/styles.css +1 -1
- package/package.json +45 -39
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,36 @@
|
|
|
3
3
|
All notable changes to `@pieai/swimmer-ui-kit`.
|
|
4
4
|
Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
|
|
5
5
|
|
|
6
|
+
## 1.2.0 — 2026-07-18
|
|
7
|
+
|
|
8
|
+
Purely additive: an official "overlay glass" HUD surface tone plus a compact
|
|
9
|
+
density, for products that float kit chrome over a live scene (TuringPact 3D
|
|
10
|
+
tavern, SupaLuv cinematic stage). No exported component, prop, class, or token
|
|
11
|
+
was removed or renamed.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Overlay glass scope: `data-game-ui-tone="glass"` (alias class
|
|
16
|
+
`.game-ui-overlay-scope`) re-scopes semantic surface/text/elevation tokens on
|
|
17
|
+
a subtree to dark translucent glass — fill `rgba(12,14,20,0.72)`, 1px light
|
|
18
|
+
border, no clay box-shadow, warm accent hover/primary, WCAG-visible warm
|
|
19
|
+
focus ring (`--game-ui-overlay-glass-focus-ring`). Nests inside light or
|
|
20
|
+
`night` page themes.
|
|
21
|
+
- Compact density: `data-game-ui-density="compact"` (orthogonal to tone) —
|
|
22
|
+
34px control floor, tighter panel/chip padding for HUD clusters.
|
|
23
|
+
- Primitive tokens `--game-ui-overlay-glass-*` in `theme.css`; TS mirrors
|
|
24
|
+
`CLAY_OVERLAY_GLASS_TOKENS` and `GAME_UI_OVERLAY` attr/class constants.
|
|
25
|
+
- Clay `GameAssetIcon` gets a soft dark drop-shadow inside glass scope so
|
|
26
|
+
sculpted icons read on translucent dark chips.
|
|
27
|
+
- Stories/preview compare: same HUD cluster in default clay vs overlay glass
|
|
28
|
+
over a busy scene background, light and night contexts.
|
|
29
|
+
|
|
30
|
+
### Migration notes
|
|
31
|
+
|
|
32
|
+
- Consumers opt in per subtree; nothing changes without the attribute.
|
|
33
|
+
- SupaLuv can delete its `.vn-stage .game-ui-button` `!important` overrides
|
|
34
|
+
(stage.css ~217-360) after wrapping its HUD in the glass scope.
|
|
35
|
+
|
|
6
36
|
## 1.1.0 — 2026-07-13
|
|
7
37
|
|
|
8
38
|
A design-system quality pass: fixes real bugs in the existing surface
|
package/bin/swimmer-ui-check.mjs
CHANGED
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
// "token-only" bar the design-system-guide asks for.
|
|
7
7
|
//
|
|
8
8
|
// Raw colors are expected (and fine) inside token-defining blocks —
|
|
9
|
-
// :root { ... } or an attribute-selector theme block like
|
|
10
|
-
// [data-game-ui-theme='night'] / [data-
|
|
11
|
-
//
|
|
12
|
-
//
|
|
9
|
+
// :root { ... } or an attribute-selector theme/tone block like
|
|
10
|
+
// [data-game-ui-theme='night'] / [data-game-ui-tone='glass'] /
|
|
11
|
+
// [data-theme='dark'] — since that is how the design-system-guide tells
|
|
12
|
+
// consumers to re-theme or re-scope surface tones. Only raw colors inside
|
|
13
|
+
// *other* selectors (component rules) are flagged.
|
|
13
14
|
//
|
|
14
15
|
// Usage: swimmer-ui-check [dir] [--ext=css,tsx]
|
|
15
16
|
// dir directory to scan, default "src"
|
|
@@ -18,8 +19,15 @@ import { readFileSync, readdirSync, statSync } from 'node:fs';
|
|
|
18
19
|
import { extname, join, relative } from 'node:path';
|
|
19
20
|
|
|
20
21
|
const RAW_COLOR = /#[0-9a-fA-F]{3,8}\b|\brgba?\(|\bhsla?\(|\boklch\(/g;
|
|
21
|
-
const TOKEN_BLOCK_SELECTOR = /:root\b|\[data-[\w-]*theme[\w-]*\s*=/i;
|
|
22
|
-
const IGNORE_DIRS = new Set([
|
|
22
|
+
const TOKEN_BLOCK_SELECTOR = /:root\b|\[data-[\w-]*(?:theme|tone)[\w-]*\s*=/i;
|
|
23
|
+
const IGNORE_DIRS = new Set([
|
|
24
|
+
'node_modules',
|
|
25
|
+
'dist',
|
|
26
|
+
'.git',
|
|
27
|
+
'storybook-static',
|
|
28
|
+
'site-dist',
|
|
29
|
+
'build',
|
|
30
|
+
]);
|
|
23
31
|
|
|
24
32
|
function walk(dir, exts, out) {
|
|
25
33
|
for (const entry of readdirSync(dir)) {
|
|
@@ -90,7 +98,9 @@ const args = process.argv.slice(2);
|
|
|
90
98
|
const target = args.find((a) => !a.startsWith('--')) ?? 'src';
|
|
91
99
|
const extArg = args.find((a) => a.startsWith('--ext='));
|
|
92
100
|
const exts = new Set(
|
|
93
|
-
(extArg ? extArg.slice('--ext='.length).split(',') : ['css']).map((e) =>
|
|
101
|
+
(extArg ? extArg.slice('--ext='.length).split(',') : ['css']).map((e) =>
|
|
102
|
+
e.startsWith('.') ? e : `.${e}`,
|
|
103
|
+
),
|
|
94
104
|
);
|
|
95
105
|
|
|
96
106
|
const files = [];
|
|
@@ -105,7 +115,9 @@ let violationCount = 0;
|
|
|
105
115
|
for (const file of files) {
|
|
106
116
|
const text = readFileSync(file, 'utf8');
|
|
107
117
|
for (const violation of findViolations(text)) {
|
|
108
|
-
console.log(
|
|
118
|
+
console.log(
|
|
119
|
+
`${relative(process.cwd(), file)}:${violation.line}: raw color literal "${violation.text}" — use var(--game-ui-*) instead`,
|
|
120
|
+
);
|
|
109
121
|
violationCount += 1;
|
|
110
122
|
}
|
|
111
123
|
}
|
|
@@ -113,9 +125,12 @@ for (const file of files) {
|
|
|
113
125
|
if (violationCount > 0) {
|
|
114
126
|
console.error(
|
|
115
127
|
`\nswimmer-ui-check: ${violationCount} raw color literal(s) in ${files.length} file(s) under "${target}". ` +
|
|
116
|
-
'Raw colors are expected inside :root / [data-*theme*=...] token blocks
|
|
117
|
-
'but not inside component rules — see the
|
|
128
|
+
'Raw colors are expected inside :root / [data-*theme*=...] / [data-*tone*=...] token blocks ' +
|
|
129
|
+
'(that is how you re-theme or re-scope the kit) but not inside component rules — see the ' +
|
|
130
|
+
'design-system-guide "主题化配方" section.',
|
|
118
131
|
);
|
|
119
132
|
process.exit(1);
|
|
120
133
|
}
|
|
121
|
-
console.log(
|
|
134
|
+
console.log(
|
|
135
|
+
`swimmer-ui-check: 0 raw color literals in component rules across ${files.length} file(s) under "${target}". Clean.`,
|
|
136
|
+
);
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,9 @@ export declare const CLAY_COLOR_TOKENS: {
|
|
|
72
72
|
readonly shadow: "rgba(76, 52, 28, 0.24)";
|
|
73
73
|
readonly glass: "rgba(255, 248, 236, 0.82)";
|
|
74
74
|
readonly nightGlass: "rgba(31, 24, 18, 0.76)";
|
|
75
|
+
/** Official HUD-on-scene glass fill (matches SupaLuv stage chrome). */
|
|
76
|
+
readonly overlayGlass: "rgba(12, 14, 20, 0.72)";
|
|
77
|
+
readonly overlayGlassText: "#fff6ee";
|
|
75
78
|
};
|
|
76
79
|
|
|
77
80
|
export declare const CLAY_ELEVATION_TOKENS: {
|
|
@@ -268,6 +271,26 @@ export declare const CLAY_MOTION_TOKENS: {
|
|
|
268
271
|
readonly reducedMotion: "var(--game-ui-reduced-motion-policy)";
|
|
269
272
|
};
|
|
270
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Semantic CSS vars for the official overlay-glass HUD tone
|
|
276
|
+
* (`data-game-ui-tone="glass"` / `.game-ui-overlay-scope`).
|
|
277
|
+
*/
|
|
278
|
+
declare const CLAY_OVERLAY_GLASS_TOKENS: {
|
|
279
|
+
readonly bg: "var(--game-ui-overlay-glass-bg)";
|
|
280
|
+
readonly bgHover: "var(--game-ui-overlay-glass-bg-hover)";
|
|
281
|
+
readonly bgStrong: "var(--game-ui-overlay-glass-bg-strong)";
|
|
282
|
+
readonly bgPanel: "var(--game-ui-overlay-glass-bg-panel)";
|
|
283
|
+
readonly border: "var(--game-ui-overlay-glass-border)";
|
|
284
|
+
readonly borderHover: "var(--game-ui-overlay-glass-border-hover)";
|
|
285
|
+
readonly text: "var(--game-ui-overlay-glass-text)";
|
|
286
|
+
readonly textMuted: "var(--game-ui-overlay-glass-text-muted)";
|
|
287
|
+
readonly blur: "var(--game-ui-overlay-glass-blur)";
|
|
288
|
+
readonly focusRing: "var(--game-ui-overlay-glass-focus-ring)";
|
|
289
|
+
readonly primaryFill: "var(--game-ui-overlay-glass-primary-fill)";
|
|
290
|
+
};
|
|
291
|
+
export { CLAY_OVERLAY_GLASS_TOKENS }
|
|
292
|
+
export { CLAY_OVERLAY_GLASS_TOKENS as GAME_UI_OVERLAY_GLASS_TOKENS }
|
|
293
|
+
|
|
271
294
|
export declare const CLAY_RADIUS_TOKENS: {
|
|
272
295
|
readonly bead: "var(--game-ui-radius-bead)";
|
|
273
296
|
readonly control: "var(--game-ui-radius-control)";
|
|
@@ -363,6 +386,9 @@ export declare const CLAY_UI_TOKENS: {
|
|
|
363
386
|
readonly shadow: "rgba(76, 52, 28, 0.24)";
|
|
364
387
|
readonly glass: "rgba(255, 248, 236, 0.82)";
|
|
365
388
|
readonly nightGlass: "rgba(31, 24, 18, 0.76)";
|
|
389
|
+
/** Official HUD-on-scene glass fill (matches SupaLuv stage chrome). */
|
|
390
|
+
readonly overlayGlass: "rgba(12, 14, 20, 0.72)";
|
|
391
|
+
readonly overlayGlassText: "#fff6ee";
|
|
366
392
|
};
|
|
367
393
|
readonly semantic: {
|
|
368
394
|
readonly background: "var(--game-ui-bg)";
|
|
@@ -470,6 +496,19 @@ export declare const CLAY_UI_TOKENS: {
|
|
|
470
496
|
readonly buildRailCardSize: "var(--game-ui-build-rail-card-size)";
|
|
471
497
|
readonly brushNumberWidth: "var(--game-ui-brush-number-width)";
|
|
472
498
|
};
|
|
499
|
+
readonly overlayGlass: {
|
|
500
|
+
readonly bg: "var(--game-ui-overlay-glass-bg)";
|
|
501
|
+
readonly bgHover: "var(--game-ui-overlay-glass-bg-hover)";
|
|
502
|
+
readonly bgStrong: "var(--game-ui-overlay-glass-bg-strong)";
|
|
503
|
+
readonly bgPanel: "var(--game-ui-overlay-glass-bg-panel)";
|
|
504
|
+
readonly border: "var(--game-ui-overlay-glass-border)";
|
|
505
|
+
readonly borderHover: "var(--game-ui-overlay-glass-border-hover)";
|
|
506
|
+
readonly text: "var(--game-ui-overlay-glass-text)";
|
|
507
|
+
readonly textMuted: "var(--game-ui-overlay-glass-text-muted)";
|
|
508
|
+
readonly blur: "var(--game-ui-overlay-glass-blur)";
|
|
509
|
+
readonly focusRing: "var(--game-ui-overlay-glass-focus-ring)";
|
|
510
|
+
readonly primaryFill: "var(--game-ui-overlay-glass-primary-fill)";
|
|
511
|
+
};
|
|
473
512
|
};
|
|
474
513
|
|
|
475
514
|
export declare type ClayAssetGroup = keyof typeof CLAY_ASSETS;
|
|
@@ -507,7 +546,7 @@ export declare type ClayIconStyle = 'game' | 'line';
|
|
|
507
546
|
|
|
508
547
|
export declare type ClayTokenCategory = keyof typeof CLAY_UI_TOKENS;
|
|
509
548
|
|
|
510
|
-
export declare function FirstSessionHud({ authenticated, batteryCount, className, dailyStreak, iconSlots, labels, onHistory, onSettings, onWardrobe, playerName }: FirstSessionHudProps): ReactNode;
|
|
549
|
+
export declare function FirstSessionHud({ authenticated, batteryCount, className, dailyStreak, iconSlots, labels, onHistory, onSettings, onWardrobe, playerName, }: FirstSessionHudProps): ReactNode;
|
|
511
550
|
|
|
512
551
|
export declare interface FirstSessionHudIconSlots {
|
|
513
552
|
history?: ReactNode;
|
|
@@ -556,7 +595,7 @@ export declare interface FirstSessionHudProps {
|
|
|
556
595
|
playerName: string;
|
|
557
596
|
}
|
|
558
597
|
|
|
559
|
-
export declare function FirstSessionOnboarding({ labels, onDismiss, open }: FirstSessionOnboardingProps): ReactNode;
|
|
598
|
+
export declare function FirstSessionOnboarding({ labels, onDismiss, open, }: FirstSessionOnboardingProps): ReactNode;
|
|
560
599
|
|
|
561
600
|
export declare interface FirstSessionOnboardingLabels {
|
|
562
601
|
badge: string;
|
|
@@ -578,6 +617,15 @@ export declare interface FirstSessionOnboardingStep {
|
|
|
578
617
|
title: string;
|
|
579
618
|
}
|
|
580
619
|
|
|
620
|
+
/** Opt-in attribute values for the official overlay-glass HUD scope. */
|
|
621
|
+
export declare const GAME_UI_OVERLAY: {
|
|
622
|
+
readonly toneAttr: "data-game-ui-tone";
|
|
623
|
+
readonly toneGlass: "glass";
|
|
624
|
+
readonly densityAttr: "data-game-ui-density";
|
|
625
|
+
readonly densityCompact: "compact";
|
|
626
|
+
readonly scopeClass: "game-ui-overlay-scope";
|
|
627
|
+
};
|
|
628
|
+
|
|
581
629
|
export declare const GAME_UI_PREVIEW_MESSAGES: readonly GameUiHistoryEntry[];
|
|
582
630
|
|
|
583
631
|
export declare const GAME_UI_TARGETS: {
|
|
@@ -681,7 +729,7 @@ export declare const GAME_UI_TOKENS: {
|
|
|
681
729
|
readonly disabled: "var(--game-ui-disabled)";
|
|
682
730
|
};
|
|
683
731
|
|
|
684
|
-
export declare function GameActionGrid({ actions, className, density, iconLabelMode, label, style }: GameActionGridProps): ReactNode;
|
|
732
|
+
export declare function GameActionGrid({ actions, className, density, iconLabelMode, label, style, }: GameActionGridProps): ReactNode;
|
|
685
733
|
|
|
686
734
|
export declare interface GameActionGridProps {
|
|
687
735
|
actions: readonly GameUiAction[];
|
|
@@ -736,7 +784,7 @@ export declare interface GameAssetGroup {
|
|
|
736
784
|
source?: GameAssetSource;
|
|
737
785
|
}
|
|
738
786
|
|
|
739
|
-
export declare function GameAssetIcon({ className, icon, label, size, style, useSourceAsset }: GameAssetIconProps): ReactNode;
|
|
787
|
+
export declare function GameAssetIcon({ className, icon, label, size, style, useSourceAsset, }: GameAssetIconProps): ReactNode;
|
|
740
788
|
|
|
741
789
|
export declare interface GameAssetIconProps {
|
|
742
790
|
className?: string;
|
|
@@ -773,7 +821,7 @@ export declare type GameAssetSource = 'starter' | 'generated' | 'imported';
|
|
|
773
821
|
|
|
774
822
|
export declare type GameAssetStatus = 'ready' | 'generating' | 'missing' | 'placed' | 'selected' | 'error';
|
|
775
823
|
|
|
776
|
-
export declare function GameAvatar({ className, name, size, src, status }: GameAvatarProps): ReactNode;
|
|
824
|
+
export declare function GameAvatar({ className, name, size, src, status, }: GameAvatarProps): ReactNode;
|
|
777
825
|
|
|
778
826
|
export declare interface GameAvatarProps {
|
|
779
827
|
/** Display name — used as image alt text and for the initials fallback. */
|
|
@@ -1155,7 +1203,7 @@ export declare interface GameDialogProps {
|
|
|
1155
1203
|
title: string;
|
|
1156
1204
|
}
|
|
1157
1205
|
|
|
1158
|
-
export declare function GameEmptyState({ action, className, description, icon, title }: GameEmptyStateProps): ReactNode;
|
|
1206
|
+
export declare function GameEmptyState({ action, className, description, icon, title, }: GameEmptyStateProps): ReactNode;
|
|
1159
1207
|
|
|
1160
1208
|
export declare interface GameEmptyStateProps {
|
|
1161
1209
|
/** Optional clay icon shown above the title. */
|
|
@@ -1176,7 +1224,7 @@ export declare interface GameFactItem {
|
|
|
1176
1224
|
value: ReactNode;
|
|
1177
1225
|
}
|
|
1178
1226
|
|
|
1179
|
-
export declare function GameFactList({ className, density, facts, label, variant }: GameFactListProps): ReactNode;
|
|
1227
|
+
export declare function GameFactList({ className, density, facts, label, variant, }: GameFactListProps): ReactNode;
|
|
1180
1228
|
|
|
1181
1229
|
export declare interface GameFactListProps {
|
|
1182
1230
|
className?: string;
|
|
@@ -1186,7 +1234,7 @@ export declare interface GameFactListProps {
|
|
|
1186
1234
|
variant?: 'facts' | 'stats';
|
|
1187
1235
|
}
|
|
1188
1236
|
|
|
1189
|
-
export declare function GameField({ children, className, error, hint, label, required }: GameFieldProps): ReactNode;
|
|
1237
|
+
export declare function GameField({ children, className, error, hint, label, required, }: GameFieldProps): ReactNode;
|
|
1190
1238
|
|
|
1191
1239
|
export declare interface GameFieldProps {
|
|
1192
1240
|
/** The input/textarea this field labels. Rendered inside the <label>. */
|
|
@@ -1286,7 +1334,7 @@ export declare interface GameInteractionSoundOptions {
|
|
|
1286
1334
|
sfxVolume?: number;
|
|
1287
1335
|
}
|
|
1288
1336
|
|
|
1289
|
-
export declare function GameLanguageMenu({ className, currentLabel, label, options, value, defaultValue, onSelect }: GameLanguageMenuProps): ReactNode;
|
|
1337
|
+
export declare function GameLanguageMenu({ className, currentLabel, label, options, value, defaultValue, onSelect, }: GameLanguageMenuProps): ReactNode;
|
|
1290
1338
|
|
|
1291
1339
|
export declare interface GameLanguageMenuProps {
|
|
1292
1340
|
className?: string;
|
|
@@ -1377,7 +1425,7 @@ export declare const GameObjectToolbar: typeof GamePlacementToolbar;
|
|
|
1377
1425
|
|
|
1378
1426
|
export declare type GameObjectToolbarProps = GamePlacementToolbarProps;
|
|
1379
1427
|
|
|
1380
|
-
export declare function GameOrientationGate({ body, cta, badgeLabel, manualHint, preview, title }: GameOrientationGateProps): ReactNode;
|
|
1428
|
+
export declare function GameOrientationGate({ body, cta, badgeLabel, manualHint, preview, title, }: GameOrientationGateProps): ReactNode;
|
|
1381
1429
|
|
|
1382
1430
|
export declare interface GameOrientationGateProps {
|
|
1383
1431
|
body: string;
|
|
@@ -1417,7 +1465,7 @@ export declare interface GamePlacementToolbarProps {
|
|
|
1417
1465
|
title: string;
|
|
1418
1466
|
}
|
|
1419
1467
|
|
|
1420
|
-
export declare function GameProgress({ className, label, max, showValue, tone, value }: GameProgressProps): ReactNode;
|
|
1468
|
+
export declare function GameProgress({ className, label, max, showValue, tone, value, }: GameProgressProps): ReactNode;
|
|
1421
1469
|
|
|
1422
1470
|
export declare interface GameProgressProps {
|
|
1423
1471
|
/** Current value, between 0 and `max`. */
|
|
@@ -1480,7 +1528,7 @@ export declare const GameSceneHudLayout: typeof GameShell;
|
|
|
1480
1528
|
|
|
1481
1529
|
export declare type GameSceneHudLayoutProps = GameShellProps;
|
|
1482
1530
|
|
|
1483
|
-
export declare function GameSegmentedControl({ activeId, label, onSelect, options }: GameSegmentedControlProps): ReactNode;
|
|
1531
|
+
export declare function GameSegmentedControl({ activeId, label, onSelect, options, }: GameSegmentedControlProps): ReactNode;
|
|
1484
1532
|
|
|
1485
1533
|
export declare interface GameSegmentedControlProps {
|
|
1486
1534
|
activeId: string;
|