mac-human-design 0.1.19 → 0.1.20
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 +13 -0
- package/package.json +1 -1
- package/scripts/verify-macos-design.mjs +112 -1
package/changelog.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
This file tracks changes between published npm versions of `mac-human-design`.
|
|
4
4
|
|
|
5
|
+
## 0.1.20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added automated macOS design verifier coverage for icon-button alignment
|
|
10
|
+
invariants, including fixed icon button dimensions, grid centering,
|
|
11
|
+
symbol glyph centering, non-positional icon-button Motion feedback,
|
|
12
|
+
`SymbolIconButton` structure, and SF Symbol PNG normalization.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Bumped the package to `0.1.20`.
|
|
17
|
+
|
|
5
18
|
## 0.1.19
|
|
6
19
|
|
|
7
20
|
### Fixed
|
package/package.json
CHANGED
|
@@ -6,6 +6,8 @@ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."
|
|
|
6
6
|
const stylesPath = path.join(repoRoot, "src", "styles", "macosBaseUi.css");
|
|
7
7
|
const packageJsonPath = path.join(repoRoot, "package.json");
|
|
8
8
|
const wrapperPath = path.join(repoRoot, "src", "components", "MacBaseUI.tsx");
|
|
9
|
+
const symbolIconButtonPath = path.join(repoRoot, "src", "components", "SymbolIconButton.tsx");
|
|
10
|
+
const symbolServicePath = path.join(repoRoot, "src", "symbols", "systemSymbolService.ts");
|
|
9
11
|
|
|
10
12
|
function readText(filePath) {
|
|
11
13
|
return fs.readFileSync(filePath, "utf8");
|
|
@@ -43,6 +45,28 @@ const sources = new Map(
|
|
|
43
45
|
const stylesSource = readText(stylesPath);
|
|
44
46
|
const packageJson = JSON.parse(readText(packageJsonPath));
|
|
45
47
|
const wrapperSource = readText(wrapperPath);
|
|
48
|
+
const symbolIconButtonSource = readText(symbolIconButtonPath);
|
|
49
|
+
const symbolServiceSource = readText(symbolServicePath);
|
|
50
|
+
|
|
51
|
+
function getCssRuleBody(selector) {
|
|
52
|
+
const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
53
|
+
const rulePattern = new RegExp(`(?:^|\\n)${escapedSelector}\\s*\\{([\\s\\S]*?)\\}`, "g");
|
|
54
|
+
for (const match of stylesSource.matchAll(rulePattern)) {
|
|
55
|
+
const prefix = stylesSource.slice(0, match.index).trimEnd();
|
|
56
|
+
if (!prefix.endsWith(",")) {
|
|
57
|
+
return match[1];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return "";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function requireCssDeclarations(selector, declarations) {
|
|
64
|
+
const body = getCssRuleBody(selector);
|
|
65
|
+
const missingDeclarations = declarations.filter(([label, pattern]) => !pattern.test(body));
|
|
66
|
+
if (missingDeclarations.length > 0) {
|
|
67
|
+
fail(`Missing required CSS declarations for ${selector}.`, missingDeclarations.map(([label]) => label));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
46
70
|
|
|
47
71
|
const requiredStyleFeatures = [
|
|
48
72
|
["system font stack", /-apple-system,\s*BlinkMacSystemFont/],
|
|
@@ -98,6 +122,93 @@ if (motionCreateMatches.length !== 1 || !allowedMotionCreatePattern.test(wrapper
|
|
|
98
122
|
]);
|
|
99
123
|
}
|
|
100
124
|
|
|
125
|
+
requireCssDeclarations(".hd-mac-icon-button", [
|
|
126
|
+
["fixed 28px width", /width\s*:\s*28px\s*;/],
|
|
127
|
+
["fixed 28px height", /height\s*:\s*28px\s*;/],
|
|
128
|
+
["fixed 28px min-width", /min-width\s*:\s*28px\s*;/],
|
|
129
|
+
["fixed 28px min-height", /min-height\s*:\s*28px\s*;/],
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
requireCssDeclarations(".hd-mac-symbol-icon-button", [
|
|
133
|
+
["fixed 30px width", /width\s*:\s*30px\s*;/],
|
|
134
|
+
["fixed 30px height", /height\s*:\s*30px\s*;/],
|
|
135
|
+
["fixed 30px min-width", /min-width\s*:\s*30px\s*;/],
|
|
136
|
+
["fixed 30px min-height", /min-height\s*:\s*30px\s*;/],
|
|
137
|
+
]);
|
|
138
|
+
|
|
139
|
+
requireCssDeclarations(".hd-mac-symbol-icon", [
|
|
140
|
+
["single grid cell placement", /grid-area\s*:\s*1\s*\/\s*1\s*;/],
|
|
141
|
+
["flex centering display", /display\s*:\s*inline-flex\s*;/],
|
|
142
|
+
["vertical glyph centering", /align-items\s*:\s*center\s*;/],
|
|
143
|
+
["horizontal glyph centering", /justify-content\s*:\s*center\s*;/],
|
|
144
|
+
["automatic optical centering margin", /margin\s*:\s*auto\s*;/],
|
|
145
|
+
["center transform origin", /transform-origin\s*:\s*center\s*;/],
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
const sharedIconButtonRule = stylesSource.match(
|
|
149
|
+
/\.hd-mac-icon-button,\s*\n\.hd-mac-symbol-icon-button\s*\{([\s\S]*?)\}/,
|
|
150
|
+
)?.[1] ?? "";
|
|
151
|
+
const missingSharedIconButtonDeclarations = [
|
|
152
|
+
["grid icon-button layout", /display\s*:\s*inline-grid\s*;/],
|
|
153
|
+
["grid item centering", /place-items\s*:\s*center\s*;/],
|
|
154
|
+
["grid content centering", /place-content\s*:\s*center\s*;/],
|
|
155
|
+
["zero padding", /padding\s*:\s*0\s*;/],
|
|
156
|
+
["zero line-height", /line-height\s*:\s*0\s*;/],
|
|
157
|
+
["center transform origin", /transform-origin\s*:\s*center\s*;/],
|
|
158
|
+
["middle inline alignment", /vertical-align\s*:\s*middle\s*;/],
|
|
159
|
+
].filter(([, pattern]) => !pattern.test(sharedIconButtonRule));
|
|
160
|
+
|
|
161
|
+
if (missingSharedIconButtonDeclarations.length > 0) {
|
|
162
|
+
fail(
|
|
163
|
+
"Missing required shared icon-button centering declarations.",
|
|
164
|
+
missingSharedIconButtonDeclarations.map(([label]) => label),
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const iconMotionBranch = wrapperSource.match(
|
|
169
|
+
/if\s*\(\s*includesAny\(macClassName,\s*\[\s*"hd-mac-icon-button",\s*"hd-mac-help-button"\s*\]\)\s*\)\s*\{([\s\S]*?)\n\s*\}/,
|
|
170
|
+
)?.[1] ?? "";
|
|
171
|
+
if (!/whileHover\s*:\s*\{\s*scale\s*:\s*1\.04\s*\}/.test(iconMotionBranch)) {
|
|
172
|
+
fail("Icon-only controls must use center-origin scale hover feedback.", ["src/components/MacBaseUI.tsx"]);
|
|
173
|
+
}
|
|
174
|
+
if (!/whileTap\s*:\s*\{\s*scale\s*:\s*0\.94\s*\}/.test(iconMotionBranch)) {
|
|
175
|
+
fail("Icon-only controls must use center-origin scale press feedback.", ["src/components/MacBaseUI.tsx"]);
|
|
176
|
+
}
|
|
177
|
+
if (/\by\s*:/.test(iconMotionBranch)) {
|
|
178
|
+
fail("Icon-only controls must not use vertical Motion offsets.", ["src/components/MacBaseUI.tsx"]);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const symbolIconRequirements = [
|
|
182
|
+
["SymbolIconButton imports MacIconButton", /import\s+\{\s*MacIconButton,\s*MacTooltip\s*\}\s+from\s+["']\.\/MacBaseUI["']/],
|
|
183
|
+
["SymbolIconButton render element is MacIconButton", /render=\{\s*<MacIconButton\b/],
|
|
184
|
+
["SymbolIconButton applies hd-mac-symbol-icon-button class", /className=["']hd-mac-symbol-icon-button["']/],
|
|
185
|
+
["masked symbol class path", /className=["']hd-mac-symbol-icon hd-mac-symbol-icon-mask["']/],
|
|
186
|
+
["fallback symbol class path", /className=["']hd-mac-symbol-icon hd-mac-symbol-icon-fallback["']/],
|
|
187
|
+
["mask centering", /maskPosition:\s*["']center["']/],
|
|
188
|
+
["webkit mask centering", /WebkitMaskPosition:\s*["']center["']/],
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
const missingSymbolIconRequirements = symbolIconRequirements
|
|
192
|
+
.filter(([, pattern]) => !pattern.test(symbolIconButtonSource))
|
|
193
|
+
.map(([label]) => label);
|
|
194
|
+
|
|
195
|
+
if (missingSymbolIconRequirements.length > 0) {
|
|
196
|
+
fail("Missing SymbolIconButton alignment invariants.", missingSymbolIconRequirements);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const missingSymbolServiceRequirements = [
|
|
200
|
+
["transparent symbol padding trim", /trimTransparentSymbolPadding/],
|
|
201
|
+
["alpha threshold trim", /TRANSPARENT_ALPHA_THRESHOLD/],
|
|
202
|
+
["canvas crop path", /trimmedCanvas\.toDataURL\(["']image\/png["']\)/],
|
|
203
|
+
].filter(([, pattern]) => !pattern.test(symbolServiceSource));
|
|
204
|
+
|
|
205
|
+
if (missingSymbolServiceRequirements.length > 0) {
|
|
206
|
+
fail(
|
|
207
|
+
"Missing system symbol image normalization invariants.",
|
|
208
|
+
missingSymbolServiceRequirements.map(([label]) => label),
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
101
212
|
const negativeLetterSpacing = [];
|
|
102
213
|
const viewportScaledFonts = [];
|
|
103
214
|
|
|
@@ -142,5 +253,5 @@ if (process.exitCode) {
|
|
|
142
253
|
}
|
|
143
254
|
|
|
144
255
|
console.log(
|
|
145
|
-
`Verified macOS design features, typography constraints, and ${hdMacClasses.size} styled hd-mac classes.`,
|
|
256
|
+
`Verified macOS design features, icon-button alignment invariants, typography constraints, and ${hdMacClasses.size} styled hd-mac classes.`,
|
|
146
257
|
);
|