@pieai/swimmer-ui-kit 1.0.0 → 1.1.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 +113 -0
- package/bin/swimmer-ui-check.mjs +121 -0
- package/dist/fonts/OFL-Baloo2.txt +93 -0
- package/dist/fonts/OFL-Geist.txt +92 -0
- package/dist/fonts/baloo-2-latin-variable.woff2 +0 -0
- package/dist/fonts/geist-sans-latin-variable.woff2 +0 -0
- package/dist/fonts.css +1 -0
- package/dist/index.d.ts +49 -5
- package/dist/index.js +765 -696
- package/dist/preview.css +1 -0
- package/dist/styles.css +1 -1
- package/package.json +9 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,119 @@
|
|
|
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.1.0 — 2026-07-13
|
|
7
|
+
|
|
8
|
+
A design-system quality pass: fixes real bugs in the existing surface
|
|
9
|
+
(radial menu, contrast, fonts) and starts paying down the "central kitchen"
|
|
10
|
+
governance/packaging debt (token adoption checker, theme contract export,
|
|
11
|
+
demo CSS split). No exported component or prop was removed or renamed.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `GAME_UI_THEME_CONTRACT`, an exported `readonly string[]` of every
|
|
16
|
+
semantic token a complete theme (like the official `night` theme) must
|
|
17
|
+
override. Downstream custom themes (e.g. an `abyss` theme) can assert
|
|
18
|
+
their own CSS covers the same list instead of eyeballing the docs.
|
|
19
|
+
- Optional `./fonts.css` subpath: `@font-face` rules + bundled Latin-subset
|
|
20
|
+
woff2 for Baloo 2 and Geist Variable (SIL OFL), the two families
|
|
21
|
+
`theme.css`'s font stack already names. Not loading it still works
|
|
22
|
+
(progressive enhancement, system-font fallback) but non-standard font
|
|
23
|
+
weights (620/860/930) collapse to 400/700 without it.
|
|
24
|
+
- `swimmer-ui-check`, a zero-dependency bin (`npx swimmer-ui-check <dir>`)
|
|
25
|
+
that scans a consumer's own CSS/TSX for raw color literals outside
|
|
26
|
+
`:root`/`[data-*theme*]` blocks — the same "no bare colors in component
|
|
27
|
+
rules" rule `src/tokens.test.ts` enforces inside this repo, made runnable
|
|
28
|
+
against downstream code.
|
|
29
|
+
- `GameModal` gained `position="bottom"`, a mobile action-sheet variant of
|
|
30
|
+
the same native `<dialog>` (unchanged focus trap/Esc/backdrop, only the
|
|
31
|
+
frame's placement/shape/entrance differ). Replaces the hand-rolled
|
|
32
|
+
backdrop+slide-up-panel pattern some consumers were building themselves
|
|
33
|
+
(a known source of missing focus-trap/Esc handling).
|
|
34
|
+
- `GameRadialMenu` gained an `onSelect?: (id: string) => void` callback
|
|
35
|
+
(previously clicking an item did nothing).
|
|
36
|
+
- Demo site and Storybook both gained a light/night theme toggle (demo site:
|
|
37
|
+
navbar control using the kit's own `GameToggle`-style button; Storybook:
|
|
38
|
+
a global toolbar entry that sets `data-game-ui-theme` for every story).
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **`GameRadialMenu` is now actually styled.** It rendered as unstyled
|
|
43
|
+
browser-default buttons before (`.game-ui-radial-item` had no CSS rule at
|
|
44
|
+
all); it's now a real circular wheel using clock-position placement.
|
|
45
|
+
`role="menu"`/`role="menuitem"` (which had no working keyboard model)
|
|
46
|
+
changed to `role="group"` + plain buttons.
|
|
47
|
+
- **Button/tab/badge text contrast, both themes.** WCAG-measured failures
|
|
48
|
+
as low as 2.52:1 on the primary button in the night theme (need 4.5:1).
|
|
49
|
+
Fixed at the token layer only (`theme.css`): `--game-ui-accent-contrast`
|
|
50
|
+
is now a dark-ink color shared by primary/danger/success buttons, the
|
|
51
|
+
active tab/segmented pill, avatar initials, and the checkbox check —
|
|
52
|
+
component rules did not change. Two further raw-brand-color-as-text
|
|
53
|
+
spots (`--game-ui-danger` on `.game-ui-field-error`/`-required`,
|
|
54
|
+
`--game-ui-accent` on the first-session step numbers) got their own new
|
|
55
|
+
`--game-ui-danger-ink`/`--game-ui-accent-ink` tokens. HUD-chip and
|
|
56
|
+
fact-chip secondary text (`.game-ui-hud-chip small/em`,
|
|
57
|
+
`.game-ui-fact-copy small/em`) stopped fading `--game-ui-text-on-dark` to
|
|
58
|
+
72% opacity, which dropped under 4.5:1 against realistic glass-chip
|
|
59
|
+
backdrops. All of the above are locked in by an expanded WCAG contrast
|
|
60
|
+
guard test (`src/tokens.test.ts`), not just fixed once.
|
|
61
|
+
- `GameSlider`'s range input now has a token-styled clay thumb/track
|
|
62
|
+
(`::-webkit-slider-thumb`/`::-moz-range-thumb`) instead of bare
|
|
63
|
+
`accent-color`.
|
|
64
|
+
- `GameTooltip` auto-generates `aria-describedby` linking the trigger to
|
|
65
|
+
the tooltip text (was visual-only). `GameTabs` accepts an optional `id` +
|
|
66
|
+
per-tab `panelId` to auto-populate `aria-controls`.
|
|
67
|
+
- Interactive controls get a `@media (forced-colors: active)` fallback
|
|
68
|
+
(Windows High Contrast) — pressed/selected states get a real border
|
|
69
|
+
instead of relying on a `color-mix()` wash forced-colors mode ignores.
|
|
70
|
+
- Storybook's `@storybook/addon-a11y` gate went from cosmetic
|
|
71
|
+
(`test: 'todo'`) to enforced (`test: 'error'`) — a real axe violation now
|
|
72
|
+
fails `pnpm test`, not just shows up in the Storybook UI.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- Three accessibility bugs the newly-enforced Storybook a11y gate caught:
|
|
77
|
+
`GameCardFan` used an invalid `role="listitem"` on an `<article>`
|
|
78
|
+
(changed to a plain `<li>`); two scrollable job-list containers in
|
|
79
|
+
`GameContractorTools` had no keyboard focus path; `GameContractorPanel`'s
|
|
80
|
+
mobile drawer rendered the selected job twice (drawer + standalone card)
|
|
81
|
+
when open, producing duplicate ARIA landmarks.
|
|
82
|
+
- `vitest.config.ts`'s unit-test include glob was `src/**/*.test.ts` —
|
|
83
|
+
it silently excluded every `*.test.tsx` file. Five files and ~30 tests
|
|
84
|
+
had never actually run via `pnpm test` despite the command exiting 0.
|
|
85
|
+
Fixed the glob, which then surfaced (and fixed) two further dormant test
|
|
86
|
+
bugs it had been hiding.
|
|
87
|
+
- The demo site's token ledger truncated every value to `var(--…` and
|
|
88
|
+
broke token names mid-word (`TOUCHMINIM UMPX`); values now wrap instead
|
|
89
|
+
of ellipsis-truncating, and cards no longer stretch to their tallest
|
|
90
|
+
sibling in the grid.
|
|
91
|
+
|
|
92
|
+
### Breaking (packaging only — no component/prop/class/token removed)
|
|
93
|
+
|
|
94
|
+
- **`GameUiPreview`'s demo-only CSS moved to a new optional `./preview.css`
|
|
95
|
+
subpath.** It was ~13KB of stage/showcase-only rules
|
|
96
|
+
(`.game-ui-preview-*`, `.game-ui-swatch`/`.game-ui-token-*`,
|
|
97
|
+
`.game-ui-stage-world`, `.game-ui-proof-frame`, the first-session demo
|
|
98
|
+
world) that every consumer paid for in `styles.css` even though
|
|
99
|
+
`GameUiPreview` is a kit-internal showcase component almost nobody
|
|
100
|
+
renders in production. If you render `<GameUiPreview />` (as TuringPact's
|
|
101
|
+
`/ui-preview` route does), add
|
|
102
|
+
`import '@pieai/swimmer-ui-kit/preview.css'` alongside `./styles.css` or
|
|
103
|
+
it renders unstyled. Everyone else needs no code change —
|
|
104
|
+
`.game-ui-*`/`--game-ui-*` names are unchanged, only which file the CSS
|
|
105
|
+
ships in. `dist/styles.css` dropped from 89.2KB to 77.8KB minified.
|
|
106
|
+
|
|
107
|
+
## 1.0.1 — 2026-07-11
|
|
108
|
+
|
|
109
|
+
### Added
|
|
110
|
+
|
|
111
|
+
- `GameCallout`, a token-driven notice surface for wallet pitches, onboarding
|
|
112
|
+
hints, warnings, success messages, and other compact product notices.
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
|
|
116
|
+
- `GameButton` keeps a 44px minimum hit target on coarse pointers while allowing
|
|
117
|
+
denser 40px controls for precise pointers.
|
|
118
|
+
|
|
6
119
|
## 1.0.0 — 2026-07-03
|
|
7
120
|
|
|
8
121
|
1.0 is a stability contract, not a feature drop: exported components and
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Scans consumer CSS for raw color literals living in component rules
|
|
3
|
+
// instead of flowing through SwimmerUIKit tokens. Mirrors the guard check
|
|
4
|
+
// the kit runs on its own styles.css in src/tokens.test.ts, packaged so
|
|
5
|
+
// downstream products can hold their own component CSS to the same
|
|
6
|
+
// "token-only" bar the design-system-guide asks for.
|
|
7
|
+
//
|
|
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-theme='dark'] — since that is
|
|
11
|
+
// exactly how the design-system-guide tells consumers to re-theme. Only
|
|
12
|
+
// raw colors inside *other* selectors (component rules) are flagged.
|
|
13
|
+
//
|
|
14
|
+
// Usage: swimmer-ui-check [dir] [--ext=css,tsx]
|
|
15
|
+
// dir directory to scan, default "src"
|
|
16
|
+
// --ext comma-separated extensions to scan, default "css"
|
|
17
|
+
import { readFileSync, readdirSync, statSync } from 'node:fs';
|
|
18
|
+
import { extname, join, relative } from 'node:path';
|
|
19
|
+
|
|
20
|
+
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(['node_modules', 'dist', '.git', 'storybook-static', 'site-dist', 'build']);
|
|
23
|
+
|
|
24
|
+
function walk(dir, exts, out) {
|
|
25
|
+
for (const entry of readdirSync(dir)) {
|
|
26
|
+
if (IGNORE_DIRS.has(entry)) continue;
|
|
27
|
+
const full = join(dir, entry);
|
|
28
|
+
const stat = statSync(full);
|
|
29
|
+
if (stat.isDirectory()) walk(full, exts, out);
|
|
30
|
+
else if (exts.has(extname(entry))) out.push(full);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function lineFinder(text) {
|
|
35
|
+
const offsets = [0];
|
|
36
|
+
for (let i = 0; i < text.length; i += 1) if (text[i] === '\n') offsets.push(i + 1);
|
|
37
|
+
return (index) => {
|
|
38
|
+
let lo = 0;
|
|
39
|
+
let hi = offsets.length - 1;
|
|
40
|
+
while (lo < hi) {
|
|
41
|
+
const mid = (lo + hi + 1) >> 1;
|
|
42
|
+
if (offsets[mid] <= index) lo = mid;
|
|
43
|
+
else hi = mid - 1;
|
|
44
|
+
}
|
|
45
|
+
return lo + 1;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Brace-depth scan (not a real CSS parser, good enough for this lint):
|
|
51
|
+
* every `{`/`}` pushes/pops whether the block it opened is a token-defining
|
|
52
|
+
* selector, and raw colors are only reported for declarations whose
|
|
53
|
+
* innermost enclosing block is not one of those.
|
|
54
|
+
*/
|
|
55
|
+
function findViolations(css) {
|
|
56
|
+
const withoutComments = css.replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, ' '));
|
|
57
|
+
const lineOf = lineFinder(withoutComments);
|
|
58
|
+
|
|
59
|
+
const blockIsTokenScope = [];
|
|
60
|
+
let blockStart = 0;
|
|
61
|
+
let cursor = 0;
|
|
62
|
+
const violations = [];
|
|
63
|
+
|
|
64
|
+
while (cursor < withoutComments.length) {
|
|
65
|
+
const open = withoutComments.indexOf('{', cursor);
|
|
66
|
+
const close = withoutComments.indexOf('}', cursor);
|
|
67
|
+
if (open === -1 && close === -1) break;
|
|
68
|
+
|
|
69
|
+
if (open !== -1 && (close === -1 || open < close)) {
|
|
70
|
+
const selector = withoutComments.slice(blockStart, open);
|
|
71
|
+
blockIsTokenScope.push(TOKEN_BLOCK_SELECTOR.test(selector));
|
|
72
|
+
blockStart = open + 1;
|
|
73
|
+
cursor = open + 1;
|
|
74
|
+
} else {
|
|
75
|
+
const body = withoutComments.slice(blockStart, close);
|
|
76
|
+
const allowed = blockIsTokenScope.pop() ?? false;
|
|
77
|
+
if (!allowed) {
|
|
78
|
+
for (const match of body.matchAll(RAW_COLOR)) {
|
|
79
|
+
violations.push({ line: lineOf(blockStart + match.index), text: match[0] });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
blockStart = close + 1;
|
|
83
|
+
cursor = close + 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return violations;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const args = process.argv.slice(2);
|
|
90
|
+
const target = args.find((a) => !a.startsWith('--')) ?? 'src';
|
|
91
|
+
const extArg = args.find((a) => a.startsWith('--ext='));
|
|
92
|
+
const exts = new Set(
|
|
93
|
+
(extArg ? extArg.slice('--ext='.length).split(',') : ['css']).map((e) => (e.startsWith('.') ? e : `.${e}`)),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const files = [];
|
|
97
|
+
try {
|
|
98
|
+
walk(target, exts, files);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error(`swimmer-ui-check: cannot read "${target}": ${error.message}`);
|
|
101
|
+
process.exit(2);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let violationCount = 0;
|
|
105
|
+
for (const file of files) {
|
|
106
|
+
const text = readFileSync(file, 'utf8');
|
|
107
|
+
for (const violation of findViolations(text)) {
|
|
108
|
+
console.log(`${relative(process.cwd(), file)}:${violation.line}: raw color literal "${violation.text}" — use var(--game-ui-*) instead`);
|
|
109
|
+
violationCount += 1;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (violationCount > 0) {
|
|
114
|
+
console.error(
|
|
115
|
+
`\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 (that is how you re-theme the kit) ' +
|
|
117
|
+
'but not inside component rules — see the design-system-guide "主题化配方" section.',
|
|
118
|
+
);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
console.log(`swimmer-ui-check: 0 raw color literals in component rules across ${files.length} file(s) under "${target}". Clean.`);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2019 The Baloo 2 Project Authors (https://github.com/EkType/Baloo2)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Copyright (c) 2023 Vercel, in collaboration with basement.studio
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
-----------------------------------------------------------
|
|
8
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
9
|
+
-----------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
PREAMBLE
|
|
12
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
13
|
+
development of collaborative font projects, to support the font creation
|
|
14
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
15
|
+
open framework in which fonts may be shared and improved in partnership
|
|
16
|
+
with others.
|
|
17
|
+
|
|
18
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
19
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
20
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
21
|
+
redistributed and/or sold with any software provided that any reserved
|
|
22
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
23
|
+
however, cannot be released under any other type of license. The
|
|
24
|
+
requirement for fonts to remain under this license does not apply
|
|
25
|
+
to any document created using the fonts or their derivatives.
|
|
26
|
+
|
|
27
|
+
DEFINITIONS
|
|
28
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
29
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
30
|
+
include source files, build scripts and documentation.
|
|
31
|
+
|
|
32
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
33
|
+
copyright statement(s).
|
|
34
|
+
|
|
35
|
+
"Original Version" refers to the collection of Font Software components as
|
|
36
|
+
distributed by the Copyright Holder(s).
|
|
37
|
+
|
|
38
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
39
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
40
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
41
|
+
new environment.
|
|
42
|
+
|
|
43
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
44
|
+
writer or other person who contributed to the Font Software.
|
|
45
|
+
|
|
46
|
+
PERMISSION AND CONDITIONS
|
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
48
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
49
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
50
|
+
Software, subject to the following conditions:
|
|
51
|
+
|
|
52
|
+
1) Neither the Font Software nor any of its individual components,
|
|
53
|
+
in Original or Modified Versions, may be sold by itself.
|
|
54
|
+
|
|
55
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
56
|
+
redistributed and/or sold with any software, provided that each copy
|
|
57
|
+
contains the above copyright notice and this license. These can be
|
|
58
|
+
included either as stand-alone text files, human-readable headers or
|
|
59
|
+
in the appropriate machine-readable metadata fields within text or
|
|
60
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
61
|
+
|
|
62
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
63
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
64
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
65
|
+
presented to the users.
|
|
66
|
+
|
|
67
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
68
|
+
Software shall not be used to promote, endorse or advertise any
|
|
69
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
70
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
71
|
+
permission.
|
|
72
|
+
|
|
73
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
74
|
+
must be distributed entirely under this license, and must not be
|
|
75
|
+
distributed under any other license. The requirement for fonts to
|
|
76
|
+
remain under this license does not apply to any document created
|
|
77
|
+
using the Font Software.
|
|
78
|
+
|
|
79
|
+
TERMINATION
|
|
80
|
+
This license becomes null and void if any of the above conditions are
|
|
81
|
+
not met.
|
|
82
|
+
|
|
83
|
+
DISCLAIMER
|
|
84
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
85
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
86
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
87
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
88
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
89
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
90
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
91
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
92
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
Binary file
|
package/dist/fonts.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:"Baloo 2";font-style:normal;font-weight:400 800;font-display:swap;src:url(./fonts/baloo-2-latin-variable.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Geist Variable;font-style:normal;font-weight:100 900;font-display:swap;src:url(./fonts/geist-sans-latin-variable.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
package/dist/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export declare const CLAY_ASSETS: {
|
|
|
55
55
|
|
|
56
56
|
export declare const CLAY_COLOR_TOKENS: {
|
|
57
57
|
readonly ink: "#3b2d23";
|
|
58
|
-
readonly inkMuted: "#
|
|
58
|
+
readonly inkMuted: "#786250";
|
|
59
59
|
readonly parchment: "#fff8ec";
|
|
60
60
|
readonly parchmentDeep: "#f4e2c6";
|
|
61
61
|
readonly cream: "#f3e8d8";
|
|
@@ -346,7 +346,7 @@ export declare const CLAY_TYPE_TOKENS: {
|
|
|
346
346
|
export declare const CLAY_UI_TOKENS: {
|
|
347
347
|
readonly colors: {
|
|
348
348
|
readonly ink: "#3b2d23";
|
|
349
|
-
readonly inkMuted: "#
|
|
349
|
+
readonly inkMuted: "#786250";
|
|
350
350
|
readonly parchment: "#fff8ec";
|
|
351
351
|
readonly parchmentDeep: "#f4e2c6";
|
|
352
352
|
readonly cream: "#f3e8d8";
|
|
@@ -593,6 +593,17 @@ export declare const GAME_UI_TARGETS: {
|
|
|
593
593
|
readonly mobileLandscapeProofHeightPx: 390;
|
|
594
594
|
};
|
|
595
595
|
|
|
596
|
+
/**
|
|
597
|
+
* The semantic `--game-ui-*` custom properties a *complete* theme must
|
|
598
|
+
* override for full fidelity — this is the same list the official
|
|
599
|
+
* `[data-game-ui-theme='night']` block in theme.css satisfies, enforced by
|
|
600
|
+
* a guard test in src/tokens.test.ts. A downstream product building its own
|
|
601
|
+
* full theme (e.g. `[data-game-ui-theme='abyss']`) can reuse this constant
|
|
602
|
+
* to check its own CSS for the same completeness instead of eyeballing it —
|
|
603
|
+
* see "自定义第三主题" in design-system-guide.md for a usage example.
|
|
604
|
+
*/
|
|
605
|
+
export declare const GAME_UI_THEME_CONTRACT: readonly ["--game-ui-bg", "--game-ui-surface", "--game-ui-surface-raised", "--game-ui-panel", "--game-ui-panel-strong", "--game-ui-panel-deep", "--game-ui-text", "--game-ui-text-muted", "--game-ui-accent", "--game-ui-accent-bright", "--game-ui-secondary", "--game-ui-success", "--game-ui-success-bright", "--game-ui-danger", "--game-ui-danger-bright", "--game-ui-warning", "--game-ui-focus-ring", "--game-ui-border-subtle", "--game-ui-border-strong", "--game-ui-disabled", "--game-ui-ink-deep", "--game-ui-border-ink", "--game-ui-wood", "--game-ui-ink-title", "--game-ui-ink-heading"];
|
|
606
|
+
|
|
596
607
|
export declare const GAME_UI_TOKENS: {
|
|
597
608
|
readonly iconSm: "var(--game-ui-asset-icon-sm)";
|
|
598
609
|
readonly iconMd: "var(--game-ui-asset-icon-md)";
|
|
@@ -892,6 +903,21 @@ export declare interface GameButtonProps extends ButtonHTMLAttributes<HTMLButton
|
|
|
892
903
|
|
|
893
904
|
export declare type GameButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'success';
|
|
894
905
|
|
|
906
|
+
/**
|
|
907
|
+
* Compact product notice (wallet pitch, soft warnings, onboarding hints).
|
|
908
|
+
* Token-driven; products may still override cinema theme in host CSS.
|
|
909
|
+
*/
|
|
910
|
+
export declare function GameCallout({ heading, children, tone, className, ...props }: GameCalloutProps): ReactNode;
|
|
911
|
+
|
|
912
|
+
export declare interface GameCalloutProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
913
|
+
/** Visible heading (not HTML title attribute). */
|
|
914
|
+
readonly heading?: ReactNode;
|
|
915
|
+
readonly children: ReactNode;
|
|
916
|
+
readonly tone?: GameCalloutTone;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
export declare type GameCalloutTone = 'neutral' | 'info' | 'warning' | 'success' | 'danger';
|
|
920
|
+
|
|
895
921
|
export declare function GameCardFan({ cards, className, label }: GameCardFanProps): ReactNode;
|
|
896
922
|
|
|
897
923
|
export declare interface GameCardFanCard {
|
|
@@ -1300,7 +1326,7 @@ export declare interface GameMaterialSwatchesProps {
|
|
|
1300
1326
|
'data-testid'?: string | undefined;
|
|
1301
1327
|
}
|
|
1302
1328
|
|
|
1303
|
-
export declare function GameModal({ children, className, closeLabel, closeOnBackdrop, footer, onClose, open, size, title, }: GameModalProps): ReactNode;
|
|
1329
|
+
export declare function GameModal({ children, className, closeLabel, closeOnBackdrop, footer, onClose, open, position, size, title, }: GameModalProps): ReactNode;
|
|
1304
1330
|
|
|
1305
1331
|
export declare interface GameModalProps {
|
|
1306
1332
|
children: ReactNode;
|
|
@@ -1312,6 +1338,13 @@ export declare interface GameModalProps {
|
|
|
1312
1338
|
/** Called for every close intent: Esc, backdrop click, and close button. */
|
|
1313
1339
|
onClose: () => void;
|
|
1314
1340
|
open: boolean;
|
|
1341
|
+
/**
|
|
1342
|
+
* `'bottom'` anchors the frame to the viewport's bottom edge (rounded top
|
|
1343
|
+
* corners only, safe-area-aware padding, slide-up entrance) for mobile
|
|
1344
|
+
* action sheets — same native <dialog> underneath, so focus trap/Esc/
|
|
1345
|
+
* backdrop/top-layer come free either way. Defaults to `'center'`.
|
|
1346
|
+
*/
|
|
1347
|
+
position?: 'center' | 'bottom';
|
|
1315
1348
|
size?: 'sm' | 'md' | 'lg';
|
|
1316
1349
|
title: string;
|
|
1317
1350
|
}
|
|
@@ -1406,7 +1439,7 @@ export declare interface GamePromptProps {
|
|
|
1406
1439
|
title: string;
|
|
1407
1440
|
}
|
|
1408
1441
|
|
|
1409
|
-
export declare function GameRadialMenu({ items, label }: GameRadialMenuProps): ReactNode;
|
|
1442
|
+
export declare function GameRadialMenu({ items, label, onSelect }: GameRadialMenuProps): ReactNode;
|
|
1410
1443
|
|
|
1411
1444
|
declare interface GameRadialMenuItem {
|
|
1412
1445
|
id: string;
|
|
@@ -1416,6 +1449,7 @@ declare interface GameRadialMenuItem {
|
|
|
1416
1449
|
export declare interface GameRadialMenuProps {
|
|
1417
1450
|
items: readonly GameRadialMenuItem[];
|
|
1418
1451
|
label: string;
|
|
1452
|
+
onSelect?: (id: string) => void;
|
|
1419
1453
|
}
|
|
1420
1454
|
|
|
1421
1455
|
export declare interface GameRobotCrewMember {
|
|
@@ -1514,12 +1548,21 @@ export declare type GameSurfaceLayout = 'auto' | 'desktop' | 'mobile';
|
|
|
1514
1548
|
export declare interface GameTabItem {
|
|
1515
1549
|
id: string;
|
|
1516
1550
|
label: string;
|
|
1551
|
+
/** id of the tabpanel this tab controls; wires aria-controls when set. */
|
|
1552
|
+
panelId?: string;
|
|
1517
1553
|
}
|
|
1518
1554
|
|
|
1519
|
-
export declare function GameTabs({ activeId, onSelect, tabs }: GameTabsProps): ReactNode;
|
|
1555
|
+
export declare function GameTabs({ activeId, id, onSelect, tabs }: GameTabsProps): ReactNode;
|
|
1520
1556
|
|
|
1521
1557
|
export declare interface GameTabsProps {
|
|
1522
1558
|
activeId: string;
|
|
1559
|
+
/**
|
|
1560
|
+
* Base id for this tabs instance (defaults to a generated one). Each tab
|
|
1561
|
+
* button's DOM id is `${id}-${tab.id}` — pass an explicit id so your own
|
|
1562
|
+
* `role="tabpanel"` elements can reference it via aria-labelledby (and set
|
|
1563
|
+
* GameTabItem.panelId so the tab points back via aria-controls).
|
|
1564
|
+
*/
|
|
1565
|
+
id?: string;
|
|
1523
1566
|
onSelect?: (id: string) => void;
|
|
1524
1567
|
tabs: readonly GameTabItem[];
|
|
1525
1568
|
}
|
|
@@ -1667,6 +1710,7 @@ export declare interface GameToggleProps extends Pick<ButtonHTMLAttributes<HTMLB
|
|
|
1667
1710
|
export declare function GameTooltip({ children, label }: GameTooltipProps): ReactNode;
|
|
1668
1711
|
|
|
1669
1712
|
export declare interface GameTooltipProps {
|
|
1713
|
+
/** A single focusable trigger element (e.g. GameIconButton). */
|
|
1670
1714
|
children: ReactNode;
|
|
1671
1715
|
label: string;
|
|
1672
1716
|
}
|