chore: initial DSMMG v0.2 — refonte architecturale complète
Mise en place du Design System ManageMate Group v0.2 — refonte du
système de tokens (préfixe --mmg-color-*), 9 presets accent
user-themable validés WCAG AA, overlays Radix UI + Floating UI,
Storybook 8 + Vitest + axe-core en CI, doc Astro Starlight,
DESIGN.md (format google-labs-code) et exports tokens DTCG/CSS/
TS/Figma/Tailwind v3 et v4.
- 4 packages monorepo pnpm : @managemate/{tokens,css,react,icons}
- 62 composants React headless-first (Sheet, HoverCard, ContextMenu,
Slider, ToggleGroup, AvatarGroup, UserCard, ProfileHeader,
MetricCard, PricingCard, FeatureCard, Text/Display/Eyebrow/Lead…)
- Lint contraste WCAG : 37/37 paires AA, branché CI
- Toast pile Sonner-style avec ResizeObserver
- Theming user (9 presets) sans casser sémantique fixe
- Identité Synapse (rose #D12B6A) préservée
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
// DSMMG icon builder
|
||||
// - Émet un bundle complet (icons.css) avec base + toutes les classes
|
||||
// - Émet aussi des modules par icône (each/<name>.css) pour permettre le
|
||||
// tree-shaking côté consommateur (import "@managemate/icons/each/check-line").
|
||||
// - Émet le module base.css (la classe .mmg-icon + sizes) en stand-alone,
|
||||
// utile quand on n'importe que des icônes individuelles.
|
||||
import { readFile, writeFile, mkdir, rm } from "node:fs/promises";
|
||||
import { join, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { existsSync } from "node:fs";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const REMIX_DIR = join(__dirname, "node_modules", "remixicon", "icons");
|
||||
const DIST_DIR = join(__dirname, "dist");
|
||||
const EACH_DIR = join(DIST_DIR, "each");
|
||||
|
||||
if (existsSync(DIST_DIR)) await rm(DIST_DIR, { recursive: true });
|
||||
await mkdir(EACH_DIR, { recursive: true });
|
||||
|
||||
const ICONS = [
|
||||
["Arrows", "arrow-right"],
|
||||
["Arrows", "arrow-left"],
|
||||
["Arrows", "arrow-up"],
|
||||
["Arrows", "arrow-down"],
|
||||
["Arrows", "arrow-right-up"],
|
||||
["Arrows", "arrow-go-back"],
|
||||
["Arrows", "expand-up-down"],
|
||||
["System", "external-link"],
|
||||
["System", "check"],
|
||||
["System", "close"],
|
||||
["System", "add"],
|
||||
["System", "subtract"],
|
||||
["System", "search-2"],
|
||||
["System", "filter-3"],
|
||||
["System", "more"],
|
||||
["System", "more-2"],
|
||||
["System", "menu"],
|
||||
["System", "settings-3"],
|
||||
["System", "refresh"],
|
||||
["System", "delete-bin"],
|
||||
["Design", "edit"],
|
||||
["System", "share"],
|
||||
["System", "download"],
|
||||
["System", "upload"],
|
||||
["System", "information"],
|
||||
["System", "alert"],
|
||||
["System", "error-warning"],
|
||||
["System", "checkbox-circle"],
|
||||
["System", "close-circle"],
|
||||
["System", "question"],
|
||||
["System", "spam"],
|
||||
["System", "shield-check"],
|
||||
["User & Faces", "user"],
|
||||
["User & Faces", "user-add"],
|
||||
["User & Faces", "team"],
|
||||
["User & Faces", "account-circle"],
|
||||
["System", "logout-box-r"],
|
||||
["System", "login-box"],
|
||||
["System", "lock"],
|
||||
["System", "lock-unlock"],
|
||||
["System", "eye"],
|
||||
["System", "eye-off"],
|
||||
["Business", "mail"],
|
||||
["Business", "mail-send"],
|
||||
["Communication", "message-2"],
|
||||
["Device", "phone"],
|
||||
["Media", "notification-3"],
|
||||
["Communication", "chat-3"],
|
||||
["Business", "global"],
|
||||
["Business", "calendar"],
|
||||
["Business", "calendar-check"],
|
||||
["System", "time"],
|
||||
["System", "history"],
|
||||
["Document", "file-text"],
|
||||
["Document", "file"],
|
||||
["Document", "folder"],
|
||||
["Document", "folder-open"],
|
||||
["Document", "file-pdf"],
|
||||
["Document", "file-copy"],
|
||||
["Editor", "attachment"],
|
||||
["Document", "draft"],
|
||||
["Business", "inbox"],
|
||||
["Map", "rocket-2"],
|
||||
["Buildings", "home-4"],
|
||||
["Buildings", "building"],
|
||||
["Buildings", "store-2"],
|
||||
["Buildings", "community"],
|
||||
["Map", "map-pin-2"],
|
||||
["Map", "map-2"],
|
||||
["Finance", "money-euro-circle"],
|
||||
["Finance", "bank-card"],
|
||||
["Finance", "shopping-cart-2"],
|
||||
["Finance", "shopping-bag-3"],
|
||||
["Finance", "price-tag-3"],
|
||||
["Finance", "coins"],
|
||||
["Business", "briefcase-4"],
|
||||
["Business", "line-chart"],
|
||||
["Business", "bar-chart"],
|
||||
["Business", "pie-chart"],
|
||||
["Business", "stack"],
|
||||
["System", "dashboard"],
|
||||
["System", "apps-2"],
|
||||
["System", "function"],
|
||||
["Business", "presentation"],
|
||||
["Document", "newspaper"],
|
||||
["Document", "article"],
|
||||
["Document", "book-open"],
|
||||
["Business", "bookmark-3"],
|
||||
["Health & Medical", "heart-3"],
|
||||
["System", "star"],
|
||||
["System", "thumb-up"],
|
||||
["Design", "palette"],
|
||||
["Design", "magic"],
|
||||
["Weather", "flashlight"],
|
||||
["Weather", "sun"],
|
||||
["Weather", "moon"],
|
||||
];
|
||||
|
||||
const BASE_CSS = `/* DSMMG icons — base (auto-generated). */
|
||||
.mmg-icon {
|
||||
display: inline-block;
|
||||
width: 1.25em;
|
||||
height: 1.25em;
|
||||
vertical-align: -0.225em;
|
||||
background: currentColor;
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-size: contain;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.mmg-icon--xs { width: 12px; height: 12px; }
|
||||
.mmg-icon--sm { width: 14px; height: 14px; }
|
||||
.mmg-icon--md { width: 18px; height: 18px; }
|
||||
.mmg-icon--lg { width: 24px; height: 24px; }
|
||||
.mmg-icon--xl { width: 32px; height: 32px; }
|
||||
.mmg-icon--2xl { width: 48px; height: 48px; }
|
||||
`;
|
||||
|
||||
const rules = [];
|
||||
const names = [];
|
||||
const missing = [];
|
||||
|
||||
for (const [category, base, alias] of ICONS) {
|
||||
for (const variant of ["line", "fill"]) {
|
||||
const file = join(REMIX_DIR, category, `${base}-${variant}.svg`);
|
||||
if (!existsSync(file)) {
|
||||
missing.push(`${category}/${base}-${variant}`);
|
||||
continue;
|
||||
}
|
||||
const svg = (await readFile(file, "utf8"))
|
||||
.replace(/[\r\n]+/g, "")
|
||||
.replace(/"/g, "'")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
const url = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
||||
const className = `${alias ?? base}-${variant}`;
|
||||
const rule = `.mmg-icon-${className} { mask-image: url("${url}"); -webkit-mask-image: url("${url}"); }`;
|
||||
rules.push(rule);
|
||||
names.push(className);
|
||||
|
||||
// Module subset par icône — n'inclut PAS la base, à charger séparément ou
|
||||
// implicitement via @managemate/icons/base.
|
||||
await writeFile(join(EACH_DIR, `${className}.css`), rule + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Bundle complet — base + toutes les classes
|
||||
await writeFile(join(DIST_DIR, "icons.css"), BASE_CSS + "\n" + rules.join("\n") + "\n");
|
||||
// Base seule — utile pour ceux qui font du subset
|
||||
await writeFile(join(DIST_DIR, "base.css"), BASE_CSS);
|
||||
|
||||
await writeFile(join(DIST_DIR, "icons.json"), JSON.stringify(names, null, 2));
|
||||
await writeFile(
|
||||
join(DIST_DIR, "names.js"),
|
||||
`export default ${JSON.stringify(names, null, 2)};\n`,
|
||||
);
|
||||
await writeFile(
|
||||
join(DIST_DIR, "names.d.ts"),
|
||||
`declare const names: string[];\nexport default names;\n`,
|
||||
);
|
||||
|
||||
console.log(`Built ${names.length} icon classes (${ICONS.length} icons × 2 variants)`);
|
||||
console.log(` - dist/icons.css (bundle, ${BASE_CSS.length + rules.join("\n").length} bytes)`);
|
||||
console.log(` - dist/base.css (base only)`);
|
||||
console.log(` - dist/each/<name>.css (${names.length} per-icon modules)`);
|
||||
if (missing.length) {
|
||||
console.warn(`Missing ${missing.length} files:`, missing.slice(0, 5));
|
||||
}
|
||||
Generated
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@managemate/icons",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@managemate/icons",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"remixicon": "^4.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/remixicon": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/remixicon/-/remixicon-4.9.1.tgz",
|
||||
"integrity": "sha512-36gLSoujkabnCFZFDyP17VNh9piuBA/rsXUb4auSJWLGsHVXtmxLj/EM5FjaEAGnk8oIAj1Azob/DZ2N+90lAQ==",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@managemate/icons",
|
||||
"version": "0.1.0",
|
||||
"description": "DSMMG icon system — CSS classes mmg-icon-* + per-icon subset modules",
|
||||
"license": "UNLICENSED",
|
||||
"private": true,
|
||||
"sideEffects": [
|
||||
"*.css"
|
||||
],
|
||||
"main": "./dist/icons.css",
|
||||
"style": "./dist/icons.css",
|
||||
"exports": {
|
||||
".": {
|
||||
"style": "./dist/icons.css",
|
||||
"default": "./dist/icons.css"
|
||||
},
|
||||
"./base": "./dist/base.css",
|
||||
"./each/*": "./dist/each/*.css",
|
||||
"./names": {
|
||||
"types": "./dist/names.d.ts",
|
||||
"default": "./dist/names.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node build.mjs"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"build.mjs"
|
||||
],
|
||||
"dependencies": {
|
||||
"remixicon": "^4.9.1"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user