@monoes/monodesign 1.2.4 → 1.2.6
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/README.md +6 -6
- package/cli/engine/engines/browser/drivers.mjs +82 -1
- package/cli/engine/rules/checks.mjs +24 -1
- package/dist/antipatterns.d.ts +28 -0
- package/dist/antipatterns.d.ts.map +1 -0
- package/dist/antipatterns.js +108 -0
- package/dist/antipatterns.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/{src/index.ts → dist/index.js} +1 -1
- package/dist/index.js.map +1 -0
- package/dist/rules.d.ts +37 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +97 -0
- package/dist/rules.js.map +1 -0
- package/dist/tokens.d.ts +91 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +91 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +9 -5
- package/skill/reference/hooks.md +2 -2
- package/skill/scripts/hook-admin.mjs +51 -18
- package/skill/scripts/live/sveltekit-adapter.mjs +11 -6
- package/skill/scripts/live-inject.mjs +20 -7
- package/skill/scripts/live-server.mjs +38 -2
- package/src/antipatterns.ts +0 -164
- package/src/rules.ts +0 -129
- package/src/tokens.ts +0 -99
package/src/rules.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared design rules — the invariants every monodesign generation must satisfy.
|
|
3
|
-
* These mirror the "Absolute bans" and "Shared design laws" in the skill.
|
|
4
|
-
*
|
|
5
|
-
* Where a ban has a corresponding mechanical detector rule in the engine
|
|
6
|
-
* registry (cli/engine/registry/antipatterns.mjs), its id and description are
|
|
7
|
-
* pulled from that registry at load time instead of being hand-copied here —
|
|
8
|
-
* one source of truth, no drift between "what generation avoids" and "what
|
|
9
|
-
* detection flags". Bans with no `engineRuleId` are composition/judgment
|
|
10
|
-
* calls the detector cannot mechanically check (holistic layout patterns);
|
|
11
|
-
* they exist here for generation-time guidance only.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// Typed as plain string so tsc emits a true dynamic import instead of trying
|
|
15
|
-
// to type-resolve the untyped .mjs engine module (matches antipatterns.ts).
|
|
16
|
-
const REGISTRY_SPECIFIER: string = '../cli/engine/registry/antipatterns.mjs';
|
|
17
|
-
|
|
18
|
-
interface EngineRuleEntry {
|
|
19
|
-
id: string;
|
|
20
|
-
name: string;
|
|
21
|
-
description: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let registryPromise: Promise<EngineRuleEntry[] | null> | undefined;
|
|
25
|
-
|
|
26
|
-
async function loadRegistry(): Promise<EngineRuleEntry[] | null> {
|
|
27
|
-
registryPromise ??= import(REGISTRY_SPECIFIER).then(
|
|
28
|
-
(mod) => (mod as { ANTIPATTERNS: EngineRuleEntry[] }).ANTIPATTERNS,
|
|
29
|
-
() => null,
|
|
30
|
-
);
|
|
31
|
-
return registryPromise;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface AbsoluteBan {
|
|
35
|
-
id: string;
|
|
36
|
-
rule: string;
|
|
37
|
-
description: string;
|
|
38
|
-
/** Engine registry rule id this ban is mechanically detected by, if any. */
|
|
39
|
-
engineRuleId?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const ABSOLUTE_BANS_STATIC: AbsoluteBan[] = [
|
|
43
|
-
{
|
|
44
|
-
id: 'side-tab',
|
|
45
|
-
rule: 'No side-stripe borders',
|
|
46
|
-
description:
|
|
47
|
-
'border-left or border-right > 1px as a colored accent on cards/list items/callouts is never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.',
|
|
48
|
-
engineRuleId: 'side-tab',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
id: 'gradient-text',
|
|
52
|
-
rule: 'No gradient text',
|
|
53
|
-
description:
|
|
54
|
-
'background-clip:text with a gradient is decorative and never meaningful. Use a single solid color; emphasis via weight or size.',
|
|
55
|
-
engineRuleId: 'gradient-text',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: 'glassmorphism-default',
|
|
59
|
-
rule: 'No glassmorphism as default',
|
|
60
|
-
description:
|
|
61
|
-
'Blurs and glass cards used decoratively. Rare and purposeful, or nothing.',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
id: 'hero-metric-template',
|
|
65
|
-
rule: 'No hero-metric template',
|
|
66
|
-
description:
|
|
67
|
-
'Big number + small label + supporting stats + gradient accent is a SaaS cliché. Find a distinctive composition instead.',
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: 'identical-card-grid',
|
|
71
|
-
rule: 'No identical card grids',
|
|
72
|
-
description:
|
|
73
|
-
'Same-sized cards with icon + heading + text, repeated endlessly, signals a lack of hierarchy. Vary size, weight, or content structure.',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
id: 'modal-first',
|
|
77
|
-
rule: 'Modal is not the first thought',
|
|
78
|
-
description:
|
|
79
|
-
'Modals are usually laziness. Exhaust inline / progressive disclosure alternatives first.',
|
|
80
|
-
},
|
|
81
|
-
];
|
|
82
|
-
|
|
83
|
-
/** Static ban list — id/rule/description as authored here (may drift from the engine registry's wording for bans that also have a detector rule). */
|
|
84
|
-
export const ABSOLUTE_BANS = ABSOLUTE_BANS_STATIC;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Same ban list, with descriptions for detector-backed bans (`engineRuleId`
|
|
88
|
-
* set) replaced by the live text from the engine registry. Falls back to the
|
|
89
|
-
* static description when the registry can't be loaded (e.g. package not
|
|
90
|
-
* fully installed) or the referenced rule id is missing.
|
|
91
|
-
*/
|
|
92
|
-
export async function getAbsoluteBans(): Promise<AbsoluteBan[]> {
|
|
93
|
-
const registry = await loadRegistry();
|
|
94
|
-
if (!registry) return ABSOLUTE_BANS_STATIC;
|
|
95
|
-
const byId = new Map(registry.map((r) => [r.id, r]));
|
|
96
|
-
return ABSOLUTE_BANS_STATIC.map((ban) => {
|
|
97
|
-
const engineRule = ban.engineRuleId ? byId.get(ban.engineRuleId) : undefined;
|
|
98
|
-
return engineRule ? { ...ban, description: engineRule.description } : ban;
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export const COLOR_STRATEGIES = ['restrained', 'committed', 'full-palette', 'drenched'] as const;
|
|
103
|
-
export type ColorStrategy = (typeof COLOR_STRATEGIES)[number];
|
|
104
|
-
|
|
105
|
-
export const SHADOW_MAX_ALPHA = 0.15;
|
|
106
|
-
|
|
107
|
-
/** Validates a shadow string does not exceed the max alpha. */
|
|
108
|
-
export function shadowAlphaComplies(shadow: string): boolean {
|
|
109
|
-
const matches = shadow.match(/rgba?\([^)]+\)/g) ?? [];
|
|
110
|
-
for (const m of matches) {
|
|
111
|
-
const parts = m.replace(/rgba?\(/, '').replace(')', '').split(',').map(Number);
|
|
112
|
-
const alpha = parts.length === 4 ? parts[3] : 1;
|
|
113
|
-
if (alpha > SHADOW_MAX_ALPHA) return false;
|
|
114
|
-
}
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export type Register = 'brand' | 'product';
|
|
119
|
-
|
|
120
|
-
/** Infer register from surface description heuristic. */
|
|
121
|
-
export function inferRegister(surface: string): Register {
|
|
122
|
-
const lower = surface.toLowerCase();
|
|
123
|
-
const brandKeywords = ['landing', 'marketing', 'campaign', 'homepage', 'portfolio', 'blog'];
|
|
124
|
-
const productKeywords = ['dashboard', 'admin', 'app', 'settings', 'onboard', 'console'];
|
|
125
|
-
|
|
126
|
-
if (brandKeywords.some((k) => lower.includes(k))) return 'brand';
|
|
127
|
-
if (productKeywords.some((k) => lower.includes(k))) return 'product';
|
|
128
|
-
return 'product'; // safe default
|
|
129
|
-
}
|
package/src/tokens.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/** Design tokens as typed JS constants — mirrors tokens.css */
|
|
2
|
-
|
|
3
|
-
export const fontFamily = {
|
|
4
|
-
display: "'Cormorant Garamond', Georgia, serif",
|
|
5
|
-
body: "'Instrument Sans', system-ui, sans-serif",
|
|
6
|
-
mono: "'Space Grotesk', monospace",
|
|
7
|
-
} as const;
|
|
8
|
-
|
|
9
|
-
export const fontSize = {
|
|
10
|
-
xs: '0.75rem',
|
|
11
|
-
sm: '0.875rem',
|
|
12
|
-
base: '1rem',
|
|
13
|
-
lg: '1.125rem',
|
|
14
|
-
xl: '1.25rem',
|
|
15
|
-
'2xl': '1.5rem',
|
|
16
|
-
'3xl': '1.875rem',
|
|
17
|
-
'4xl': '2.25rem',
|
|
18
|
-
'5xl': '3rem',
|
|
19
|
-
'6xl': '3.75rem',
|
|
20
|
-
'7xl': '4.5rem',
|
|
21
|
-
} as const;
|
|
22
|
-
|
|
23
|
-
export const spacing = {
|
|
24
|
-
1: '4px',
|
|
25
|
-
2: '8px',
|
|
26
|
-
3: '12px',
|
|
27
|
-
4: '16px',
|
|
28
|
-
5: '20px',
|
|
29
|
-
6: '24px',
|
|
30
|
-
7: '28px',
|
|
31
|
-
8: '32px',
|
|
32
|
-
10: '40px',
|
|
33
|
-
12: '48px',
|
|
34
|
-
16: '64px',
|
|
35
|
-
20: '80px',
|
|
36
|
-
24: '96px',
|
|
37
|
-
30: '120px',
|
|
38
|
-
} as const;
|
|
39
|
-
|
|
40
|
-
export const easing = {
|
|
41
|
-
out: 'cubic-bezier(0.16, 1, 0.3, 1)',
|
|
42
|
-
outQuint: 'cubic-bezier(0.22, 1, 0.36, 1)',
|
|
43
|
-
inOut: 'cubic-bezier(0.65, 0, 0.35, 1)',
|
|
44
|
-
in: 'cubic-bezier(0.4, 0, 1, 1)',
|
|
45
|
-
} as const;
|
|
46
|
-
|
|
47
|
-
export const duration = {
|
|
48
|
-
instant: '0s',
|
|
49
|
-
fast: '0.15s',
|
|
50
|
-
base: '0.3s',
|
|
51
|
-
slow: '0.6s',
|
|
52
|
-
slower: '0.8s',
|
|
53
|
-
slowest: '1.2s',
|
|
54
|
-
} as const;
|
|
55
|
-
|
|
56
|
-
/** OKLCH color palette */
|
|
57
|
-
export const color = {
|
|
58
|
-
ink: 'oklch(10% 0 0)',
|
|
59
|
-
charcoal: 'oklch(25% 0 0)',
|
|
60
|
-
ash: 'oklch(55% 0 0)',
|
|
61
|
-
mist: 'oklch(92% 0 0)',
|
|
62
|
-
cream: 'oklch(96% 0.005 350)',
|
|
63
|
-
paper: 'oklch(98% 0 0)',
|
|
64
|
-
white: 'oklch(99.5% 0 0)',
|
|
65
|
-
accent: 'oklch(60% 0.25 350)',
|
|
66
|
-
accentHover: 'oklch(52% 0.25 350)',
|
|
67
|
-
accentDim: 'oklch(60% 0.25 350 / 0.15)',
|
|
68
|
-
accentSoft: 'oklch(60% 0.25 350 / 0.25)',
|
|
69
|
-
accentText: 'oklch(45% 0.22 350)',
|
|
70
|
-
} as const;
|
|
71
|
-
|
|
72
|
-
export const accentScale = {
|
|
73
|
-
1: 'oklch(22% 0.15 350)',
|
|
74
|
-
2: 'oklch(33% 0.20 350)',
|
|
75
|
-
3: 'oklch(42% 0.23 350)',
|
|
76
|
-
4: 'oklch(52% 0.25 350)',
|
|
77
|
-
5: 'oklch(60% 0.25 350)',
|
|
78
|
-
6: 'oklch(68% 0.22 350)',
|
|
79
|
-
7: 'oklch(76% 0.18 350)',
|
|
80
|
-
8: 'oklch(84% 0.12 350)',
|
|
81
|
-
9: 'oklch(94% 0.05 350)',
|
|
82
|
-
} as const;
|
|
83
|
-
|
|
84
|
-
export const shadow = {
|
|
85
|
-
none: 'none',
|
|
86
|
-
sm: '0 1px 3px rgba(0, 0, 0, 0.06)',
|
|
87
|
-
md: '0 4px 24px -4px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.06)',
|
|
88
|
-
lg: '0 20px 40px rgba(0, 0, 0, 0.08)',
|
|
89
|
-
accent: '0 20px 60px oklch(60% 0.25 350 / 0.15)',
|
|
90
|
-
} as const;
|
|
91
|
-
|
|
92
|
-
export const radius = {
|
|
93
|
-
none: '0',
|
|
94
|
-
sm: '4px',
|
|
95
|
-
md: '8px',
|
|
96
|
-
lg: '12px',
|
|
97
|
-
xl: '16px',
|
|
98
|
-
full: '9999px',
|
|
99
|
-
} as const;
|