@morya-ui/setup 0.3.4 → 0.3.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Morya UI contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -9,7 +9,7 @@ Docs (zh/en):
9
9
  - [Agent Skill](https://morya-space.github.io/morya-ui/docs/agent-skill) — `morya-ui-pages` behavior
10
10
  - [Quick start](https://morya-space.github.io/morya-ui/docs/quick-start) — install and first component
11
11
 
12
- Installs the UI library, copies first-party Agent skills / Cursor rules / design docs from `design-kit`, installs optional companion skills at **latest** via the [skills CLI](https://skills.sh/), merges Cursor MCP for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp), and injects `import 'morya-ui/styles.css'`.
12
+ Installs / upgrades the UI library and any existing `@morya-ui/*` packages to **latest**, copies first-party Agent skills / Cursor rules / design docs from `design-kit`, installs optional companion skills at **latest** via the [skills CLI](https://skills.sh/), merges Cursor MCP for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp), and injects `import 'morya-ui/styles.css'`.
13
13
 
14
14
  ## Usage
15
15
 
@@ -24,16 +24,19 @@ On a TTY, `full` / `ai` will prompt for optional Agent skills (required `morya-u
24
24
  Other common commands:
25
25
 
26
26
  ```bash
27
- # AI config + MCP only (library already installed)
27
+ # Upgrade deps + AI config + MCP (skips styles injection)
28
28
  npx @morya-ui/setup ai
29
29
 
30
- # Library + styles only
30
+ # Upgrade deps + styles only
31
31
  npx @morya-ui/setup app
32
32
 
33
33
  # Non-interactive skill selection
34
34
  npx @morya-ui/setup ai --yes
35
35
  npx @morya-ui/setup ai --skills=morya-ui-pages,frontend-design,impeccable
36
36
  npx @morya-ui/setup ai --skills=all
37
+
38
+ # Refresh AI template / MCP without touching dependencies
39
+ npx @morya-ui/setup ai --skip-install
37
40
  ```
38
41
 
39
42
  ### Options
@@ -46,7 +49,7 @@ npx @morya-ui/setup ai --skills=all
46
49
  | `--yes` / `-y` | Use default skills without prompting |
47
50
  | `--force` | Overwrite existing template files and the `morya-ui` MCP entry |
48
51
  | `--dry-run` | Print actions without writing or installing |
49
- | `--skip-install` | Do not install `morya-ui` |
52
+ | `--skip-install` | Do not install / upgrade `morya-ui` or `@morya-ui/*` |
50
53
  | `--skip-template` | Do not copy AI skill / rules / docs (also skips companion skill install) |
51
54
  | `--skip-mcp` | Do not write `.cursor/mcp.json` |
52
55
  | `--skip-styles` | Do not inject `styles.css` |
@@ -57,7 +60,7 @@ npx @morya-ui/setup ai --skills=all
57
60
 
58
61
  | Id | Default | Install | Role |
59
62
  | --- | --- | --- | --- |
60
- | `morya-ui-pages` | required | template (from this package) | Page generation with `M*` + golden layouts |
63
+ | `morya-ui-pages` | required | template (from this package) | Page generation with `M*` + snippets / decisions (composition-first) |
61
64
  | `frontend-design` | optional | skills CLI → `anthropics/skills` (latest) | Express / brand visual taste |
62
65
  | `fixing-accessibility` | optional | skills CLI → `ibelick/ui-skills` (latest) | A11y audit and targeted fixes |
63
66
  | `impeccable` | optional | skills CLI → `pbakaus/impeccable` (latest) | Named polish / audit / redesign passes |
@@ -66,9 +69,10 @@ Catalog: [`catalog/skills.json`](./catalog/skills.json).
66
69
 
67
70
  ### Conflict policy
68
71
 
72
+ - Dependencies: always install / upgrade `morya-ui@latest` and any existing `@morya-ui/*` (e.g. `@morya-ui/nuxt`) to `@latest` unless `--skip-install`.
69
73
  - Template files and `.cursor/rules/*`: **skip** if the destination exists (unless `--force`).
70
74
  - Companion skills (`skills-cli`): always reinstall/update to **latest** when selected.
71
- - `.cursor/mcp.json`: merge other servers; skip existing `morya-ui` entry unless `--force`.
75
+ - `.cursor/mcp.json`: merge other servers; skip existing `morya-ui` entry unless `--force`. New or forced entries use `npx -y @morya-ui/mcp@latest`.
72
76
  - `package.json` `check:colors`: add only if missing (unless `--force`).
73
77
  - Styles: inject only when an entry file is found and the import is not already present.
74
78
 
@@ -94,7 +98,7 @@ Writes / merges:
94
98
  "mcpServers": {
95
99
  "morya-ui": {
96
100
  "command": "npx",
97
- "args": ["-y", "@morya-ui/mcp"]
101
+ "args": ["-y", "@morya-ui/mcp@latest"]
98
102
  }
99
103
  }
100
104
  }
File without changes
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@morya-ui/setup",
3
3
  "type": "module",
4
- "version": "0.3.4",
5
- "packageManager": "pnpm@10.12.4",
4
+ "version": "0.3.5",
6
5
  "description": "One-shot setup for morya-ui: install the library, Cursor MCP, Agent skills, and design config.",
7
6
  "license": "MIT",
8
7
  "homepage": "https://github.com/morya-space/morya-ui/tree/main/packages/setup#readme",
@@ -32,7 +31,6 @@
32
31
  },
33
32
  "scripts": {
34
33
  "sync-template": "node ./scripts/sync-template.mjs",
35
- "build": "pnpm run sync-template",
36
- "prepublishOnly": "pnpm run build"
34
+ "build": "pnpm run sync-template"
37
35
  }
38
- }
36
+ }
package/src/cli.mjs CHANGED
@@ -1,8 +1,6 @@
1
- import { existsSync } from 'node:fs'
2
1
  import { dirname, join, resolve } from 'node:path'
3
2
  import { fileURLToPath } from 'node:url'
4
3
  import { copyTemplate } from './copy-template.mjs'
5
- import { readJson } from './fs-utils.mjs'
6
4
  import { installMoryaUi } from './install.mjs'
7
5
  import { mergeMcpConfig } from './mcp.mjs'
8
6
  import { ensureCheckColorsScript } from './package-json.mjs'
@@ -25,7 +23,8 @@ const MODES = new Set(['app', 'ai', 'full'])
25
23
  const MODE_DEFAULTS = {
26
24
  full: {},
27
25
  app: { skipTemplate: true, skipMcp: true, skipScripts: true },
28
- ai: { skipInstall: true, skipStyles: true },
26
+ // ai still upgrades morya-ui / @morya-ui/* to latest unless --skip-install
27
+ ai: { skipStyles: true },
29
28
  }
30
29
 
31
30
  const SKIP_FLAGS = {
@@ -47,15 +46,15 @@ export function printHelp() {
47
46
  console.log(`Usage: morya-ui-setup [command] [options]
48
47
 
49
48
  Commands:
50
- (default) / full Install morya-ui, AI template, MCP, styles, check:colors
51
- app Install morya-ui and inject styles.css
52
- ai Copy Agent skills / rules / DESIGN,
49
+ (default) / full Upgrade morya packages to latest, AI template, MCP, styles, check:colors
50
+ app Upgrade morya packages to latest and inject styles.css
51
+ ai Upgrade morya packages to latest, copy Agent skills / rules / DESIGN,
53
52
  merge Cursor MCP, add check:colors
54
53
 
55
54
  Default command:
56
- - install morya-ui
55
+ - install / upgrade morya-ui@latest and any existing @morya-ui/* to @latest
57
56
  - copy DESIGN.md, selected Agent skills, Cursor rules
58
- - merge .cursor/mcp.json for @morya-ui/mcp
57
+ - merge .cursor/mcp.json for @morya-ui/mcp@latest
59
58
  - inject import 'morya-ui/styles.css' into the app entry when found
60
59
  - add check:colors script when missing
61
60
 
@@ -66,7 +65,7 @@ Options:
66
65
  --yes Use default skills without prompting (CI / non-interactive)
67
66
  --force Overwrite existing template files and MCP server entry
68
67
  --dry-run Print actions without writing or installing
69
- --skip-install Skip dependency install
68
+ --skip-install Skip dependency install / upgrade
70
69
  --skip-template Skip copying AI template files
71
70
  --skip-mcp Skip writing .cursor/mcp.json
72
71
  --skip-styles Skip injecting styles.css
@@ -170,24 +169,6 @@ function rel(cwd, path) {
170
169
  return path.startsWith(cwd) ? path.slice(cwd.length).replace(/^[\\/]/, '') || path : path
171
170
  }
172
171
 
173
- /**
174
- * @param {string} cwd
175
- */
176
- function hasMoryaUiDependency(cwd) {
177
- const path = join(cwd, 'package.json')
178
- if (!existsSync(path)) return false
179
- try {
180
- const pkg = readJson(path)
181
- return Boolean(
182
- pkg.dependencies?.['morya-ui']
183
- || pkg.devDependencies?.['morya-ui']
184
- || pkg.peerDependencies?.['morya-ui'],
185
- )
186
- } catch {
187
- return false
188
- }
189
- }
190
-
191
172
  /**
192
173
  * @param {ReturnType<typeof parseArgs>} options
193
174
  */
@@ -210,13 +191,6 @@ export async function runSetup(options) {
210
191
  console.log(`@morya-ui/setup [${mode}] → ${cwd}${dryRun ? ' (dry-run)' : ''}`)
211
192
  console.log('')
212
193
 
213
- if (mode === 'ai' && !hasMoryaUiDependency(cwd)) {
214
- console.log(
215
- 'Warning: morya-ui is not listed in package.json. Run `npx @morya-ui/setup app` first (or pnpm add morya-ui).',
216
- )
217
- console.log('')
218
- }
219
-
220
194
  const catalog = loadSkillsCatalog()
221
195
  let selectedSkills = []
222
196
  let aiInclude
@@ -235,7 +209,8 @@ export async function runSetup(options) {
235
209
  console.log('')
236
210
  }
237
211
 
238
- const install = installMoryaUi(cwd, { pm, dryRun, skipInstall })
212
+ // Always ensure morya-ui@latest; also bump any existing @morya-ui/* (nuxt, mcp, …).
213
+ const install = installMoryaUi(cwd, { pm, dryRun, skipInstall, ensureCore: true })
239
214
 
240
215
  const template = skipTemplate
241
216
  ? { copied: [], skipped: [], forced: [], skippedStep: true }
@@ -262,10 +237,12 @@ export async function runSetup(options) {
262
237
  : ensureCheckColorsScript(cwd, { force, dryRun })
263
238
 
264
239
  console.log('--- Summary ---')
240
+ const pkgList = (install.packages || []).join(', ') || 'morya-ui'
265
241
  if (install.skipped) {
266
242
  console.log(`Install: skipped (${install.reason}) — would run: ${install.command}`)
267
243
  } else {
268
- console.log(`Install: ok (${install.pm}) — ${install.command}`)
244
+ console.log(`Install: upgraded to latest (${install.pm}) — ${pkgList}`)
245
+ console.log(` $ ${install.command}`)
269
246
  }
270
247
 
271
248
  if (template.skippedStep) {
package/src/install.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { join } from 'node:path'
3
3
  import { execSync } from 'node:child_process'
4
+ import { readJson } from './fs-utils.mjs'
4
5
 
5
6
  const LOCKFILES = [
6
7
  { pm: 'pnpm', file: 'pnpm-lock.yaml' },
@@ -8,6 +9,9 @@ const LOCKFILES = [
8
9
  { pm: 'npm', file: 'package-lock.json' },
9
10
  ]
10
11
 
12
+ const CORE_PACKAGE = 'morya-ui'
13
+ const SCOPE_PREFIX = '@morya-ui/'
14
+
11
15
  export function detectPackageManager(cwd, explicit) {
12
16
  if (explicit) {
13
17
  if (!['pnpm', 'yarn', 'npm'].includes(explicit)) {
@@ -21,43 +25,110 @@ export function detectPackageManager(cwd, explicit) {
21
25
  return 'pnpm'
22
26
  }
23
27
 
24
- function installCommand(pm) {
28
+ /**
29
+ * Collect morya-ui / @morya-ui/* names from package.json.
30
+ * Always includes `morya-ui` when ensureCore is true (full / app).
31
+ * @param {Record<string, unknown> | null} pkg
32
+ * @param {{ ensureCore?: boolean }} [opts]
33
+ * @returns {string[]}
34
+ */
35
+ export function collectMoryaPackages(pkg, { ensureCore = true } = {}) {
36
+ const names = new Set()
37
+ if (pkg && typeof pkg === 'object') {
38
+ for (const field of ['dependencies', 'devDependencies', 'optionalDependencies']) {
39
+ const deps = pkg[field]
40
+ if (!deps || typeof deps !== 'object') continue
41
+ for (const name of Object.keys(deps)) {
42
+ if (name === CORE_PACKAGE || name.startsWith(SCOPE_PREFIX)) {
43
+ names.add(name)
44
+ }
45
+ }
46
+ }
47
+ }
48
+ if (ensureCore) names.add(CORE_PACKAGE)
49
+ return [...names].sort()
50
+ }
51
+
52
+ /**
53
+ * @param {string} pm
54
+ * @param {string[]} packages bare package names
55
+ */
56
+ export function installCommand(pm, packages) {
57
+ const specs = packages.map((name) => `${name}@latest`)
58
+ const joined = specs.join(' ')
25
59
  switch (pm) {
26
60
  case 'pnpm':
27
- return 'pnpm add morya-ui'
61
+ return `pnpm add ${joined}`
28
62
  case 'yarn':
29
- return 'yarn add morya-ui'
63
+ return `yarn add ${joined}`
30
64
  case 'npm':
31
- return 'npm install morya-ui'
65
+ return `npm install ${joined}`
32
66
  default:
33
67
  throw new Error(`Unknown package manager: ${pm}`)
34
68
  }
35
69
  }
36
70
 
37
71
  /**
38
- * @returns {{ pm: string, command: string, skipped?: boolean, reason?: string }}
72
+ * Install / upgrade `morya-ui` and any existing `@morya-ui/*` deps to the npm `latest` tag.
73
+ * @returns {{
74
+ * pm: string,
75
+ * command: string,
76
+ * packages: string[],
77
+ * skipped?: boolean,
78
+ * reason?: string,
79
+ * }}
39
80
  */
40
- export function installMoryaUi(cwd, { pm, dryRun = false, skipInstall = false } = {}) {
81
+ export function installMoryaUi(cwd, {
82
+ pm,
83
+ dryRun = false,
84
+ skipInstall = false,
85
+ ensureCore = true,
86
+ } = {}) {
41
87
  const resolved = detectPackageManager(cwd, pm)
42
- const command = installCommand(resolved)
88
+ const pkgPath = join(cwd, 'package.json')
89
+
90
+ let pkg = null
91
+ if (existsSync(pkgPath)) {
92
+ try {
93
+ pkg = readJson(pkgPath)
94
+ } catch {
95
+ pkg = null
96
+ }
97
+ }
98
+
99
+ const packages = collectMoryaPackages(pkg, { ensureCore })
100
+ const command = packages.length
101
+ ? installCommand(resolved, packages)
102
+ : installCommand(resolved, [CORE_PACKAGE])
43
103
 
44
104
  if (skipInstall) {
45
- return { pm: resolved, command, skipped: true, reason: 'skip-install' }
105
+ return { pm: resolved, command, packages, skipped: true, reason: 'skip-install' }
46
106
  }
47
107
 
48
- if (!existsSync(join(cwd, 'package.json'))) {
108
+ if (!existsSync(pkgPath)) {
49
109
  return {
50
110
  pm: resolved,
51
111
  command,
112
+ packages,
52
113
  skipped: true,
53
114
  reason: 'no-package-json',
54
115
  }
55
116
  }
56
117
 
118
+ if (!packages.length) {
119
+ return {
120
+ pm: resolved,
121
+ command,
122
+ packages,
123
+ skipped: true,
124
+ reason: 'no-morya-packages',
125
+ }
126
+ }
127
+
57
128
  if (dryRun) {
58
- return { pm: resolved, command, skipped: true, reason: 'dry-run' }
129
+ return { pm: resolved, command, packages, skipped: true, reason: 'dry-run' }
59
130
  }
60
131
 
61
132
  execSync(command, { cwd, stdio: 'inherit', shell: true })
62
- return { pm: resolved, command }
133
+ return { pm: resolved, command, packages }
63
134
  }
package/src/mcp.mjs CHANGED
@@ -5,7 +5,7 @@ import { readJson, writeJson } from './fs-utils.mjs'
5
5
  const SERVER_NAME = 'morya-ui'
6
6
  const SERVER_CONFIG = {
7
7
  command: 'npx',
8
- args: ['-y', '@morya-ui/mcp'],
8
+ args: ['-y', '@morya-ui/mcp@latest'],
9
9
  }
10
10
 
11
11
  /**
@@ -5,10 +5,10 @@ description: >
5
5
  morya-ui component library — admin CRUD (list, form, dashboard, detail,
6
6
  settings), auth and onboarding, empty and error states, wizards, overlays,
7
7
  marketing/landing and pricing pages, docs chrome, and hybrid product UI.
8
- Trigger on: morya-ui, M* components, --m-* tokens, golden pages, 后台页,
9
- 列表页, 表单页, 仪表盘, 登录页, 注册, 空状态, 向导, 落地页, 官网, landing,
10
- login, dashboard, settings, onboarding, or “用组件库做页面”. Prefer this
11
- skill over generic frontend-design, impeccable, or ui-ux-pro-max when the
8
+ Trigger on: morya-ui, M* components, --m-* tokens, golden pages, page snippets,
9
+ 后台页, 列表页, 表单页, 仪表盘, 登录页, 注册, 空状态, 向导, 落地页, 官网,
10
+ landing, login, dashboard, settings, onboarding, or “用组件库做页面”. Prefer
11
+ this skill over generic frontend-design, impeccable, or ui-ux-pro-max when the
12
12
  implementation stack is morya-ui; those companions may deepen taste and polish
13
13
  after structure/contract are fixed (see references/optional-companions.md).
14
14
  Do not use for backend-only work or for authoring new components inside the
@@ -22,7 +22,9 @@ Guide agents that **consume morya-ui** across the full product surface — not o
22
22
  Two layers always apply:
23
23
 
24
24
  1. **Contract** — only `M*` controls, `--m-*` tokens, real APIs (MCP/docs). Never invent props or mix UI kits.
25
- 2. **Craft** — pick the right surface pattern, then apply intentional visual direction (distilled from Frontend Design / Impeccable / UI-UX-Pro-Max ideas). Admin golden pages stay disciplined; expressive surfaces (landing, auth brand moments, empty states) may take a justified aesthetic risk — still on-token and on-component.
25
+ 2. **Craft** — pick the right surface pattern, then apply intentional visual direction (distilled from Frontend Design / Impeccable / UI-UX-Pro-Max ideas). Ops stays disciplined; expressive surfaces (landing, auth brand moments, empty states) may take a justified aesthetic risk — still on-token and on-component.
26
+
27
+ **Default build path (composition-first):** pin surface → L2 decisions + page snippets → craft → validate. Golden pages are an **optional** whole-page block-order check — not the default clone target.
26
28
 
27
29
  When companions conflict with this skill or project `DESIGN.md`, **this skill wins**.
28
30
 
@@ -30,14 +32,14 @@ When companions conflict with this skill or project `DESIGN.md`, **this skill wi
30
32
 
31
33
  | Lane | Surfaces | Primary references |
32
34
  | --- | --- | --- |
33
- | **Ops** | list, form, dashboard, detail, settings, filter drawer, CRUD dialog | [page-layouts.md](references/page-layouts.md), golden pages |
34
- | **Account** | login, register, invite, forgot/reset password, profile | [surfaces.md](references/surfaces.md) § Account |
35
- | **Flow** | onboarding, empty state, wizard/stepper, success/result | [surfaces.md](references/surfaces.md) § Flow |
35
+ | **Ops** | list, form, dashboard, detail, settings, filter drawer, CRUD dialog | [page-layouts.md](references/page-layouts.md) block order + snippets |
36
+ | **Account** | login, register, invite, forgot/reset password, profile | [surfaces.md](references/surfaces.md) § Account + `auth-split-shell` |
37
+ | **Flow** | onboarding, empty state, wizard/stepper, success/result | [surfaces.md](references/surfaces.md) § Flow + empty/result/wizard snippets |
36
38
  | **System** | 404 / error, permission denied, maintenance | [surfaces.md](references/surfaces.md) § System |
37
39
  | **Express** | marketing landing, pricing, feature showcase, docs marketing chrome | [surfaces.md](references/surfaces.md) § Express + [visual-craft.md](references/visual-craft.md) |
38
- | **Overlay** | dialog, drawer, popover, command menu as the main UI | [surfaces.md](references/surfaces.md) § Overlay |
40
+ | **Overlay** | dialog, drawer, popover, command menu as the main UI | [surfaces.md](references/surfaces.md) § Overlay + form-in-dialog/drawer snippets |
39
41
 
40
- Unclear brief → ask **one** short question, or default: Ops → closest golden page; public marketing → Express.
42
+ Unclear brief → ask **one** short question, or default: Ops → closest page-layout checklist + snippets; public marketing → Express.
41
43
 
42
44
  Full taxonomy: [references/surfaces.md](references/surfaces.md).
43
45
 
@@ -45,7 +47,7 @@ Full taxonomy: [references/surfaces.md](references/surfaces.md).
45
47
 
46
48
  1. `morya-ui` installed; `morya-ui/styles.css` imported.
47
49
  2. Prefer `@morya-ui/mcp` — never invent prop / event / slot names.
48
- 3. Golden pages, component APIs, and feedback rules come from `@morya-ui/mcp`. Without MCP, use this skill's `references/`. Project `DESIGN.md` overrides generic taste when the AI pack is merged.
50
+ 3. Component APIs, decision recipes, page snippets, and feedback rules come from `@morya-ui/mcp`. Golden pages are optional assembly demos. Without MCP, use this skill's `references/`. Project `DESIGN.md` overrides generic taste when the AI pack is merged.
49
51
 
50
52
  ## Workflow
51
53
 
@@ -57,69 +59,69 @@ State explicitly (even briefly in thinking):
57
59
  - **Audience** — who uses this screen
58
60
  - **Surface** — from the map above
59
61
  - **Single job** — what the first viewport must accomplish
60
- - **Style direction** — resolve in this order (see [style-presets.md](references/style-presets.md)):
61
- 1. User **reference** (screenshot / mock / existing page / “像 XX”) → extract cues, map to `--m-*` + `M*`
62
- 2. User **named preset** (`soft` / 柔和留白 / …) → apply it
63
- 3. **Prompt cues** (行业/气质) → infer a preset and name it
64
- 4. Still unclear → ask **one** question with 3–4 presets; if “直接写” → domain heuristic (**not** always `quiet`)
62
+ - **Style direction** — resolve in this order (see [style-presets.md](references/style-presets.md); **no preset catalog**):
63
+ 1. User **reference** or **explicit description** → **must follow** (map to `--m-*` + `M*`; never substitute another face)
64
+ 2. No description, but **clear prompt cues** → infer and **state your reading** in one sentence
65
+ 3. **Uncertain** → **ask once** for a description or reference; do not invent the full look first
66
+ 4. User says “直接写 / 你看着办” with still no cues → quiet flat on-token admin face, **say so**; never default glass/neon/aurora
65
67
 
66
- Golden pages lock **structure/API**, not the only aesthetic. Blindly cloning golden visuals makes pages feel stiff.
68
+ Golden pages (when used) lock **block order**, not aesthetics. Blindly cloning golden visuals makes pages feel stiff — prefer composing snippets.
67
69
 
68
- For Express / branded Account moments, also draft a tiny **design plan** (see [visual-craft.md](references/visual-craft.md)): palette roles mapped to `--m-*` (extend only if the project already customizes theme), type roles, layout concept, one signature element. For Ops, a named preset + Ops polish is enough unless the user asks for a redesign.
70
+ For Express / branded Account moments, also draft a tiny **design plan** (see [visual-craft.md](references/visual-craft.md)): palette roles mapped to `--m-*` (extend only if the project already customizes theme), type roles, layout concept, one signature element. For Ops, Ops polish + the resolved direction is enough unless the user asks for a redesign.
69
71
 
70
72
  ### 2. Load the smallest useful references
71
73
 
72
74
  | Need | Prefer (MCP) | Else read |
73
75
  | --- | --- | --- |
74
- | Ops pattern | `recommend_page` → **`get_golden_page`** (mirror structure; craft from style direction) | [page-layouts.md](references/page-layouts.md) |
75
- | Style direction | `recommend_page({ style })` / **`list_style_presets`** / **`get_style_preset`** | [style-presets.md](references/style-presets.md) |
76
- | Account / Express / empty / result | `recommend_page` → `get_golden_page` (`login-page` / `landing-page` / `empty-state` / `result-page`) | [surfaces.md](references/surfaces.md) |
76
+ | Ops pattern + snippets | `recommend_page` → **`suggestedSnippets`** / **`get_page_snippet`** + **`recommend_component`** | [page-layouts.md](references/page-layouts.md) + [decision-recipes.md](references/decision-recipes.md) |
77
+ | Style direction | `recommend_page({ style })` / **`get_style_direction`** | [style-presets.md](references/style-presets.md) |
78
+ | Account / Express / empty / result | snippets (`auth-split-shell`, `empty-block`, `result-block`, …) + `recommend_page` | [surfaces.md](references/surfaces.md) |
79
+ | Optional whole-page block order | `get_golden_page` only when unsure of section order or user asks to mirror a golden sample | [page-layouts.md](references/page-layouts.md) |
77
80
  | Visual direction | — | [visual-craft.md](references/visual-craft.md) + [style-presets.md](references/style-presets.md) |
78
- | Components / **API truth** | `search` / **`get_component`** / `get_example` / **`recommend_component`** (includes L2 recipes) | [decision-recipes.md](references/decision-recipes.md) + [component-index.md](references/component-index.md) |
81
+ | Components / **API truth** | `search` / **`get_component`** / `get_example` / **`recommend_component`** (L2 recipes + `relatedSnippets`) | [decision-recipes.md](references/decision-recipes.md) + [component-index.md](references/component-index.md) |
79
82
  | Tokens / rules | `get_design_rules` | [design-system.md](references/design-system.md) |
80
- | Snippet | `get_page_snippet` | golden / surface excerpt |
81
83
  | Feedback API | — | [feedback.md](references/feedback.md) |
82
84
  | **Required checks** | **`validate_usage`** (every `M*` you used) + `validate_page` | [review-checklist.md](references/review-checklist.md) |
83
85
 
84
86
  ### 3. Compose
85
87
 
86
- **Ops:** mirror golden-page **block order**; apply the resolved **style preset** (or reference cues) for density/chrome/copy; prefer `MPage*` over custom chrome. Do not freeze every Ops page into identical quiet chrome. List craft variants: `list-page` (soft structure), `list-page-dense`, `list-page-rail` — `recommend_page({ style })` routes them.
88
+ **Ops:** follow [page-layouts.md](references/page-layouts.md) **block-order checklist**; fill each block with **`get_page_snippet`** / `suggestedSnippets` (filters, table, header actions, form-in-dialog, confirm-delete, …). Apply the resolved **style direction** for density/chrome/copy; prefer `MPage*` over custom chrome. Do not freeze every Ops page into identical chrome. List density/sider cues (`dense` / `rail`) inform craft — do not invent new golden-page variants.
87
89
 
88
- **Account / Flow / System:** centered or split shells with `MCard` / `MForm` / `MEmpty` / `MResult` (see surfaces); keep controls as `M*`. Persistent form errors use field `errorMessage` or a token-styled `role="alert"` — `<MMessage>` is the `message` host, not an inline alert.
90
+ **Account / Flow / System:** centered or split shells with `MCard` / `MForm` / `MEmpty` / `MResult` (see surfaces + snippets); keep controls as `M*`. Persistent form errors use field `errorMessage` or a token-styled `role="alert"` — `<MMessage>` is the `message` host, not an inline alert.
89
91
 
90
92
  **Express:** hero + sections with intentional hierarchy; interactive bits still `MButton` / `MTag` / etc.; atmosphere via layout, motion, and tokens — not a second component library.
91
93
 
92
- **Overlay:** build the host page lightly; put the real job inside `MDialog` / `MDrawer` / `MCommandMenu`.
94
+ **Overlay:** build the host page lightly; put the real job inside `MDialog` / `MDrawer` / `MCommandMenu` (use `form-in-dialog` / `form-in-drawer` snippets).
93
95
 
94
96
  ### 4. Wire real API usage
95
97
 
96
98
  - Import from `morya-ui` (or documented subpath + style).
97
- - **Selection + key props:** call MCP **`recommend_component`** (by query or `decision` id) and apply the returned **recipe** (`props` / `slots` / `events`) and **antiPatterns**. Without MCP, read [decision-recipes.md](references/decision-recipes.md). Then confirm full API with `get_component` / `get_example`.
98
- - Forms: `MForm` + fields; `@submit` + `type="submit"` (or documented footer button pattern on `form-in-dialog`).
99
+ - **Selection + key props:** call MCP **`recommend_component`** (by query or `decision` id) and apply the returned **recipe** (`props` / `slots` / `events`), **antiPatterns**, and **`relatedSnippets`**. Without MCP, read [decision-recipes.md](references/decision-recipes.md). Then confirm full API with `get_component` / `get_example`.
100
+ - Forms: `MForm` + fields; `@submit` + `type="submit"` (or documented footer button pattern on `form-in-dialog` snippet).
99
101
  - Tables: `columns` + `rows` + `row-key`; `#cell-{key}`. There is no `data` prop. For full-viewport admin lists whose main job is one table, consider `MPageContent fill` + `MTable fill paginator`; skip `fill` for embedded/short/whole-page-scroll cases (see [page-layouts.md](references/page-layouts.md)).
100
102
  - Enums → `MSelect` / `MTreeSelect`; action menus → `MDropdown`.
101
- - Destructive → `MConfirmDialog` / `MConfirmPopup` (`confirm-choice`).
103
+ - Destructive → `MConfirmDialog` / `MConfirmPopup` (`confirm-choice` + `confirm-delete` snippet).
102
104
  - Feedback → default **`message`**; `toast` only for summary+detail / async; persistent form errors → `errorMessage` / `role="alert"` (`feedback-choice`). See [feedback.md](references/feedback.md).
103
105
  - Motion → intensity with `useMotion` (`full` / `reduced` / `none`); overlay enter/exit with `transition` prop or `createMoryaUI({ motion: { transitions } })` — do not invent a second animation stack. Prefer MCP / docs `motion` guide.
104
106
  - **Before craft:** for each unfamiliar or newly written `M*` usage, call MCP **`get_component` / `get_example`**, then **`validate_usage`**. Fix every `unknown-prop` / `unknown-event` before delivery.
105
- - `recommend_page(includeScaffold: true)` returns the **golden page source** when one exists — remap copy/data only; never treat generated fallback as the visual target.
107
+ - `recommend_page(includeScaffold: true)` may return golden source as a **structure reference** — remap copy/data only; default path does **not** require cloning the whole page. Never treat generated fallback as the visual target.
106
108
 
107
109
  ### 5. Craft pass (always — lane-aware + companions)
108
110
 
109
111
  Run **before** delivery. Do not stop at a structurally correct shell.
110
112
 
111
- 1. Resolve **style direction** ([style-presets.md](references/style-presets.md)) — reference → preset → cues → ask.
113
+ 1. Resolve **style direction** ([style-presets.md](references/style-presets.md)) — reference/description first; else prompt cues; else **ask**; never silent AI face. **No preset catalog.**
112
114
  2. Apply lane craft from [visual-craft.md](references/visual-craft.md):
113
- - **Ops / Operate:** style preset + § Ops polish (one primary, menu icons, `MStatus`, designed empty, no decorative cards).
114
- - **Account / Flow:** one calm brand or empty-state cue from § Atmosphere; form errors via `errorMessage` / token `role="alert"`.
115
- - **Express / Persuade:** short design plan + one signature; avoid AI-default looks; optional 1–2 token-only motions via `useMotion`.
115
+ - **Ops / Operate:** resolved direction + § Ops polish (one primary, menu icons, `MStatus`, designed empty, no decorative cards).
116
+ - **Account / Flow:** one calm brand or empty-state cue from § Shell recipes; form errors via `errorMessage` / token `role="alert"`.
117
+ - **Express / Persuade:** short design plan + one signature; avoid AI-default looks; optional 1–2 token-only motions via `useMotion`. Signature ≠ unearned gradient/glass/neon.
116
118
  3. **If companions are already installed** (see [optional-companions.md](references/optional-companions.md)):
117
- - Express / brand → may load **`frontend-design`** for POV after contract is fixed
118
- - User asks 更大胆/更克制/polish/audit → may load **`impeccable`** command (`bolder` / `quieter` / `polish` / …)
119
- - Mood/industry keywords only → optional **`ui-ux-pro-max`** search, then map to tokens/preset
119
+ - Express / brand → may load **`frontend-design`** for POV after contract **and style direction** are fixed
120
+ - User asks 更大胆/更克制/polish/audit → may load **`impeccable`** command (`bolder` / `quieter` / `polish` / …) **inside** the resolved direction
121
+ - Mood/industry keywords only → optional **`ui-ux-pro-max`** search, then map to `--m-*` (not a preset id)
120
122
  - a11y pass → optional **`fixing-accessibility`** after visual
121
- - Max **one** visual companion per task; always remediate with `M*` + `--m-*`
122
- 4. If companions are **absent**, use distilled visual-craft / style-presets — do **not** block or ask to install mid-task.
123
+ - Max **one** visual companion per task; always remediate with `M*` + `--m-*`; strip companion-added AI atmosphere the user did not ask for
124
+ 4. If companions are **absent**, use distilled visual-craft / style-direction — do **not** block or ask to install mid-task.
123
125
  5. **All lanes:** responsive, focus visible, domain-real copy. User **reference** overrides companion taste within the morya contract.
124
126
 
125
127
  Named polish modes (`quieter` | `bolder` | `clarify` | `audit` | …): extra pass when the user asks to improve an existing screen.
@@ -141,10 +143,12 @@ Do not deliver with unresolved `unknown-prop` / `unknown-event`.
141
143
  - No hand-rolled table/modal when `MTable` / `MDialog` / `MDrawer` fit.
142
144
  - No invented props / events / slots.
143
145
  - No defaulting every success to `toast`.
144
- - No substituting a generated scaffold for `get_golden_page` when a golden sample exists.
145
- - Ops surfaces follow golden layouts first — do not replace them with marketing heroes.
146
+ - No substituting a generated scaffold for a real golden sample when the user asked to mirror one — but default path composes snippets, not full-page clones.
147
+ - Ops surfaces follow page-layout **block order** — do not replace them with marketing heroes.
146
148
  - Express surfaces still use `M*` for controls and `--m-*` for color/space; do not introduce shadcn/Element/etc. stacks suggested by generic design skills.
147
149
  - Soft-load companions only; never require Impeccable / UI-UX-Pro-Max / Frontend Design to be installed.
150
+ - Do **not** invent decorative glass / neon / aurora / neumorph / full-page gradients unless the **user reference or description** clearly asks for them.
151
+ - Do **not** add new golden-page craft variants (`list-page-*`); express density/sider via style direction + polish.
148
152
 
149
153
  ## Soft companions
150
154
 
@@ -154,7 +158,7 @@ If already installed in the consumer project, **combine** them after structure +
154
158
  | --- | --- | --- |
155
159
  | `frontend-design` | Express / branded Account moments | Distinctive design plan + signature (taste) |
156
160
  | `impeccable` | Polish / bolder / quieter / audit / delight asks | Named Operate/Persuade craft passes |
157
- | `ui-ux-pro-max` | Mood / industry keyword search for Express | Keywords → map to `--m-*` + style preset |
161
+ | `ui-ux-pro-max` | Mood / industry keyword search for Express | Keywords → map to `--m-*` (no preset ids) |
158
162
  | `fixing-accessibility` | a11y audit after visual | Names, keyboard, focus on top of `M*` |
159
163
 
160
164
  Routing, conflict rules, and load budget: [optional-companions.md](references/optional-companions.md). Distilled craft in [visual-craft.md](references/visual-craft.md) + [style-presets.md](references/style-presets.md) keeps this skill **standalone**.
@@ -164,7 +168,7 @@ Routing, conflict rules, and load budget: [optional-companions.md](references/op
164
168
  - Vue 3 `<script setup lang="ts">`.
165
169
  - PascalCase `M*` in templates.
166
170
  - Domain-real copy and data shapes (not placeholder “示例 / Name / No data” when the brief names a product).
167
- - Scoped CSS minimal; tokens only (`color-mix` / gradients from `--m-*` OK; control widths may be inline).
171
+ - Scoped CSS minimal; tokens only (`color-mix` OK). Prefer **flat** surfaces; gradients / glass / glow **only** when the user/reference asks (control widths may be inline).
168
172
  - Craft pass completed for the lane (see step 5).
169
173
  - For multi-file asks: sensible `views/` / `components/` split; otherwise one SFC is fine.
170
174
 
@@ -173,9 +177,9 @@ Routing, conflict rules, and load budget: [optional-companions.md](references/op
173
177
  | File | Read when |
174
178
  | --- | --- |
175
179
  | [surfaces.md](references/surfaces.md) | Choosing / composing non-Ops (and hybrid) surfaces |
176
- | [page-layouts.md](references/page-layouts.md) | Ops golden layouts |
177
- | [style-presets.md](references/style-presets.md) | Style resolution + named presets users can pick |
178
- | [visual-craft.md](references/visual-craft.md) | Ops polish, atmosphere recipes, anti-defaults, polish modes |
180
+ | [page-layouts.md](references/page-layouts.md) | Ops block-order checklists (fill with snippets) |
181
+ | [style-presets.md](references/style-presets.md) | Style resolution (no preset catalog) |
182
+ | [visual-craft.md](references/visual-craft.md) | Ops polish, shell recipes, anti-defaults, polish modes |
179
183
  | [design-system.md](references/design-system.md) | Principles, tokens, bans |
180
184
  | [component-index.md](references/component-index.md) | Catalog + decision-id index |
181
185
  | [decision-recipes.md](references/decision-recipes.md) | Scenario → component → key props (generated; offline MCP mirror) |