Files
DSMMG/packages/icons/build.mjs
T
Dinawo 62317f2ad7
Release / Release / open changeset PR (push) Has been cancelled
CI / Build, typecheck, test, a11y (push) Has been cancelled
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>
2026-05-04 22:08:38 +02:00

192 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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));
}