onemore-design 1.0.0
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 +21 -0
- package/SKILL.md +180 -0
- package/bin/onemore.js +23 -0
- package/data/audit/hig-checklist.csv +39 -0
- package/data/components/content.csv +17 -0
- package/data/components/controls.csv +21 -0
- package/data/components/feedback.csv +17 -0
- package/data/components/input.csv +11 -0
- package/data/components/navigation.csv +15 -0
- package/data/foundations/colors.csv +38 -0
- package/data/foundations/corners.csv +13 -0
- package/data/foundations/elevation.csv +17 -0
- package/data/foundations/spacing.csv +21 -0
- package/data/foundations/typography.csv +26 -0
- package/data/patterns/animation.csv +24 -0
- package/data/patterns/gestures.csv +11 -0
- package/data/patterns/interaction.csv +16 -0
- package/data/patterns/layout.csv +20 -0
- package/data/platforms/ios.csv +21 -0
- package/data/platforms/macos.csv +16 -0
- package/data/platforms/visionos.csv +11 -0
- package/data/platforms/watchos.csv +11 -0
- package/data/platforms/web-apple.csv +21 -0
- package/data/reasoning/apple-reasoning.csv +16 -0
- package/data/stacks/astro.csv +21 -0
- package/data/stacks/flutter.csv +29 -0
- package/data/stacks/html-tailwind.csv +26 -0
- package/data/stacks/nativewind.csv +26 -0
- package/data/stacks/nextjs.csv +26 -0
- package/data/stacks/nuxtjs.csv +21 -0
- package/data/stacks/react-native.csv +26 -0
- package/data/stacks/react.csv +26 -0
- package/data/stacks/shadcn.csv +25 -0
- package/data/stacks/svelte.csv +21 -0
- package/data/stacks/swiftui.csv +31 -0
- package/data/stacks/uikit.csv +21 -0
- package/data/stacks/vue.csv +21 -0
- package/package.json +51 -0
- package/scripts/__init__.py +0 -0
- package/scripts/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/scripts/__pycache__/exporter.cpython-314.pyc +0 -0
- package/scripts/__pycache__/platforms.cpython-314.pyc +0 -0
- package/scripts/__pycache__/redesign.cpython-314.pyc +0 -0
- package/scripts/core.py +242 -0
- package/scripts/design_system.py +291 -0
- package/scripts/exporter.py +717 -0
- package/scripts/platforms.py +309 -0
- package/scripts/redesign.py +758 -0
- package/scripts/search.py +426 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""OneMore Multi-Platform Distribution"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
PROJECT_DIR = Path(__file__).parent.parent
|
|
9
|
+
|
|
10
|
+
PLATFORMS = {
|
|
11
|
+
"claude-code": {
|
|
12
|
+
"type": "global", "path": "~/.claude/skills/onemore", "name": "Claude Code",
|
|
13
|
+
"detect": {"dirs": ["~/.claude"], "commands": ["claude"]}
|
|
14
|
+
},
|
|
15
|
+
"codex": {
|
|
16
|
+
"type": "global", "path": "~/.codex/skills/onemore", "name": "Codex",
|
|
17
|
+
"detect": {"dirs": ["~/.codex"], "commands": ["codex"]}
|
|
18
|
+
},
|
|
19
|
+
"qoder": {
|
|
20
|
+
"type": "global", "path": "~/.qoder/skills/onemore", "name": "Qoder",
|
|
21
|
+
"detect": {"dirs": ["~/.qoder"], "commands": ["qoder"]}
|
|
22
|
+
},
|
|
23
|
+
"antigravity": {
|
|
24
|
+
"type": "global", "path": "~/.antigravity/plugins/onemore", "name": "Antigravity",
|
|
25
|
+
"detect": {"dirs": ["~/.antigravity"], "commands": ["antigravity"]}
|
|
26
|
+
},
|
|
27
|
+
"cursor": {
|
|
28
|
+
"type": "project", "path": ".cursor/rules/onemore.mdc", "name": "Cursor",
|
|
29
|
+
"detect": {"project_dirs": [".cursor"], "commands": ["cursor"]}
|
|
30
|
+
},
|
|
31
|
+
"windsurf": {
|
|
32
|
+
"type": "project", "path": ".windsurf/rules/onemore.md", "name": "Windsurf",
|
|
33
|
+
"detect": {"project_dirs": [".windsurf"], "commands": ["windsurf"]}
|
|
34
|
+
},
|
|
35
|
+
"copilot": {
|
|
36
|
+
"type": "project", "path": ".github/copilot-instructions.md", "name": "GitHub Copilot", "mode": "append",
|
|
37
|
+
"detect": {"project_dirs": [".github"], "commands": ["gh"]}
|
|
38
|
+
},
|
|
39
|
+
"gemini": {
|
|
40
|
+
"type": "project", "path": "GEMINI.md", "name": "Gemini CLI", "mode": "append",
|
|
41
|
+
"detect": {"dirs": [], "commands": ["gemini"]}
|
|
42
|
+
},
|
|
43
|
+
"cline": {
|
|
44
|
+
"type": "project", "path": ".clinerules/onemore.md", "name": "Cline",
|
|
45
|
+
"detect": {"project_dirs": [".clinerules"], "commands": []}
|
|
46
|
+
},
|
|
47
|
+
"roo": {
|
|
48
|
+
"type": "project", "path": ".roo/rules/onemore.md", "name": "Roo Code",
|
|
49
|
+
"detect": {"project_dirs": [".roo"], "commands": []}
|
|
50
|
+
},
|
|
51
|
+
"kiro": {
|
|
52
|
+
"type": "project", "path": ".kiro/rules/onemore.md", "name": "Kiro",
|
|
53
|
+
"detect": {"project_dirs": [".kiro"], "commands": ["kiro"]}
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
def generate_project_rules():
|
|
58
|
+
"""Generate condensed Apple HIG rules for project-level installs."""
|
|
59
|
+
return '''# OneMore — Apple HIG Design Rules
|
|
60
|
+
|
|
61
|
+
> Apply these rules when building UI. Every element should look like an Apple product.
|
|
62
|
+
|
|
63
|
+
## Core Principles
|
|
64
|
+
1. **Clarity** — Legible text, precise icons, subtle adornments
|
|
65
|
+
2. **Deference** — UI serves content, never competes
|
|
66
|
+
3. **Depth** — Visual layers and motion convey hierarchy
|
|
67
|
+
4. **Consistency** — Familiar standards and paradigms
|
|
68
|
+
5. **Direct Manipulation** — Immediate visible results
|
|
69
|
+
6. **Feedback** — Perceptible response to every action
|
|
70
|
+
|
|
71
|
+
## Priority Rules
|
|
72
|
+
|
|
73
|
+
| # | Category | Key Rule |
|
|
74
|
+
|---|----------|----------|
|
|
75
|
+
| 1 | Accessibility | 4.5:1 contrast, VoiceOver/aria labels, Dynamic Type |
|
|
76
|
+
| 2 | Touch Targets | 44pt min (iOS), 60pt (visionOS), 20pt (macOS) |
|
|
77
|
+
| 3 | Typography | SF Pro (native) or Inter/system-ui (web). Body: 17pt iOS, 13pt macOS |
|
|
78
|
+
| 4 | Colors | Semantic tokens only. Support dark mode. Never hardcode hex |
|
|
79
|
+
| 5 | Spacing | 4pt grid: 4/8/12/16/20/24/32/48 |
|
|
80
|
+
| 6 | Components | Native controls. Continuous corners (borderCurve: continuous) |
|
|
81
|
+
| 7 | Animation | Spring physics only. Never linear/ease for UI transitions |
|
|
82
|
+
| 8 | Platform | iOS != macOS != visionOS. Use platform-appropriate patterns |
|
|
83
|
+
|
|
84
|
+
## Apple Color System
|
|
85
|
+
- Text: semantic `label` color (#1d1d1f on web, NOT pure black)
|
|
86
|
+
- Background: semantic `systemBackground` (#fbfbfd on web, NOT pure white)
|
|
87
|
+
- Accent: `systemBlue` #007AFF (light) / #0A84FF (dark)
|
|
88
|
+
- Destructive: `systemRed` #FF3B30 / #FF453A
|
|
89
|
+
- Success: `systemGreen` #34C759 / #30D158
|
|
90
|
+
- Grays: systemGray through systemGray6 (6 levels, different light/dark)
|
|
91
|
+
|
|
92
|
+
## Apple Typography Scale (iOS)
|
|
93
|
+
| Style | Size | Weight |
|
|
94
|
+
|-------|------|--------|
|
|
95
|
+
| largeTitle | 34pt | Regular |
|
|
96
|
+
| title1 | 28pt | Regular |
|
|
97
|
+
| title2 | 22pt | Regular |
|
|
98
|
+
| headline | 17pt | Semibold |
|
|
99
|
+
| body | 17pt | Regular |
|
|
100
|
+
| callout | 16pt | Regular |
|
|
101
|
+
| subheadline | 15pt | Regular |
|
|
102
|
+
| footnote | 13pt | Regular |
|
|
103
|
+
| caption1 | 12pt | Regular |
|
|
104
|
+
|
|
105
|
+
## Apple Spacing Scale
|
|
106
|
+
4 → 8 → 12 → 16 → 20 → 24 → 32 → 40 → 48 (pt)
|
|
107
|
+
|
|
108
|
+
## Spring Animation Presets
|
|
109
|
+
| Preset | Response | Damping | Use |
|
|
110
|
+
|--------|----------|---------|-----|
|
|
111
|
+
| smooth | 0.5 | 1.0 | General transitions |
|
|
112
|
+
| snappy | 0.35 | 1.0 | Quick actions |
|
|
113
|
+
| bouncy | 0.5 | 0.7 | Playful interactions |
|
|
114
|
+
| interactive | 0.15 | 0.86 | Gesture-driven |
|
|
115
|
+
|
|
116
|
+
## Web Font Stack
|
|
117
|
+
```css
|
|
118
|
+
font-family: -apple-system, BlinkMacSystemFont, "Inter", system-ui, sans-serif;
|
|
119
|
+
```
|
|
120
|
+
SF Pro only on Apple platforms. Inter is the closest web fallback.
|
|
121
|
+
|
|
122
|
+
## Pre-Delivery Checklist
|
|
123
|
+
- [ ] 4pt grid spacing, no arbitrary values
|
|
124
|
+
- [ ] SF Pro (native) or Inter/system-ui (web) typography
|
|
125
|
+
- [ ] Semantic color tokens, dark mode working
|
|
126
|
+
- [ ] Continuous corners (not standard border-radius)
|
|
127
|
+
- [ ] Touch targets >= 44pt
|
|
128
|
+
- [ ] Spring animations, no linear/ease
|
|
129
|
+
- [ ] Dynamic Type / font scaling
|
|
130
|
+
- [ ] No emoji icons — SF Symbols or Lucide
|
|
131
|
+
- [ ] Platform-appropriate navigation
|
|
132
|
+
- [ ] VoiceOver/aria labels, 4.5:1 contrast
|
|
133
|
+
- [ ] Safe areas respected
|
|
134
|
+
|
|
135
|
+
## Anti-Patterns
|
|
136
|
+
| Don\'t | Do |
|
|
137
|
+
|--------|-----|
|
|
138
|
+
| border-radius: 8px | Continuous corners, correct radii (12pt buttons, 16pt cards) |
|
|
139
|
+
| Arial/Helvetica | SF Pro (native), Inter (web) |
|
|
140
|
+
| Random spacing | 4pt grid |
|
|
141
|
+
| Flat UI | Materials, vibrancy, shadows |
|
|
142
|
+
| ease-in-out | Spring physics |
|
|
143
|
+
| #000000 text | Semantic label color |
|
|
144
|
+
| Emoji icons | SF Symbols or SVG icon set |
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
*Generated by [OneMore](https://github.com/onemore) — Apple HIG Design Intelligence*
|
|
148
|
+
'''
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def init_platform(platform_name, project_dir=None):
|
|
152
|
+
"""Initialize OneMore for a specific platform."""
|
|
153
|
+
if platform_name not in PLATFORMS:
|
|
154
|
+
return {"error": f"Unknown platform: {platform_name}", "available": list(PLATFORMS.keys())}
|
|
155
|
+
|
|
156
|
+
config = PLATFORMS[platform_name]
|
|
157
|
+
|
|
158
|
+
if config["type"] == "global":
|
|
159
|
+
return _init_global(platform_name, config)
|
|
160
|
+
else:
|
|
161
|
+
return _init_project(platform_name, config, project_dir or Path.cwd())
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _init_global(platform_name, config):
|
|
165
|
+
"""Install OneMore globally for a platform (symlink or copy)."""
|
|
166
|
+
target = Path(config["path"]).expanduser()
|
|
167
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
168
|
+
|
|
169
|
+
if target.exists() or target.is_symlink():
|
|
170
|
+
return {"status": "already_installed", "platform": config["name"], "path": str(target)}
|
|
171
|
+
|
|
172
|
+
# Symlink the entire project directory
|
|
173
|
+
os.symlink(str(PROJECT_DIR), str(target))
|
|
174
|
+
return {"status": "installed", "platform": config["name"], "path": str(target), "method": "symlink"}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _init_project(platform_name, config, project_dir):
|
|
178
|
+
"""Install OneMore rules into a project directory."""
|
|
179
|
+
target = Path(project_dir) / config["path"]
|
|
180
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
181
|
+
|
|
182
|
+
rules = generate_project_rules()
|
|
183
|
+
|
|
184
|
+
# Cursor needs frontmatter
|
|
185
|
+
if platform_name == "cursor":
|
|
186
|
+
content = f"---\ndescription: Apple HIG design rules - apply when building UI\nglobs: \"**/*.{{tsx,jsx,vue,svelte,swift,html,css,scss}}\"\nalwaysApply: false\n---\n\n{rules}"
|
|
187
|
+
elif config.get("mode") == "append":
|
|
188
|
+
# Append mode: add to existing file
|
|
189
|
+
header = "\n\n<!-- OneMore: Apple HIG Design Rules -->\n"
|
|
190
|
+
footer = "\n<!-- /OneMore -->\n"
|
|
191
|
+
if target.exists():
|
|
192
|
+
existing = target.read_text()
|
|
193
|
+
if "OneMore" in existing:
|
|
194
|
+
return {"status": "already_installed", "platform": config["name"], "path": str(target)}
|
|
195
|
+
content = existing + header + rules + footer
|
|
196
|
+
else:
|
|
197
|
+
content = header.lstrip() + rules + footer
|
|
198
|
+
else:
|
|
199
|
+
content = rules
|
|
200
|
+
|
|
201
|
+
target.write_text(content)
|
|
202
|
+
return {"status": "installed", "platform": config["name"], "path": str(target)}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def detect_platforms(project_dir=None):
|
|
206
|
+
"""Auto-detect which AI platforms are installed.
|
|
207
|
+
|
|
208
|
+
Detection strategy:
|
|
209
|
+
- Global platforms: check if config dir exists in home (~/.claude, ~/.codex, etc) OR command in PATH
|
|
210
|
+
- Project platforms: check if project dir exists (.cursor/, .windsurf/, etc) OR command in PATH
|
|
211
|
+
|
|
212
|
+
Returns list of dicts with platform name, detected (bool), and reason.
|
|
213
|
+
"""
|
|
214
|
+
project_dir = Path(project_dir) if project_dir else Path.cwd()
|
|
215
|
+
results = []
|
|
216
|
+
|
|
217
|
+
for name, config in PLATFORMS.items():
|
|
218
|
+
detect = config.get("detect", {})
|
|
219
|
+
detected = False
|
|
220
|
+
reason = ""
|
|
221
|
+
|
|
222
|
+
# Check global dirs (home directory)
|
|
223
|
+
for d in detect.get("dirs", []):
|
|
224
|
+
expanded = Path(d).expanduser()
|
|
225
|
+
if expanded.exists():
|
|
226
|
+
detected = True
|
|
227
|
+
reason = f"found {d}"
|
|
228
|
+
break
|
|
229
|
+
|
|
230
|
+
# Check project dirs (current project)
|
|
231
|
+
if not detected:
|
|
232
|
+
for d in detect.get("project_dirs", []):
|
|
233
|
+
if (project_dir / d).exists():
|
|
234
|
+
detected = True
|
|
235
|
+
reason = f"found {d}/ in project"
|
|
236
|
+
break
|
|
237
|
+
|
|
238
|
+
# Check commands in PATH
|
|
239
|
+
if not detected:
|
|
240
|
+
for cmd in detect.get("commands", []):
|
|
241
|
+
if shutil.which(cmd):
|
|
242
|
+
detected = True
|
|
243
|
+
reason = f"'{cmd}' command found"
|
|
244
|
+
break
|
|
245
|
+
|
|
246
|
+
# Check if OneMore already installed for this platform
|
|
247
|
+
if config["type"] == "global":
|
|
248
|
+
install_path = Path(config["path"]).expanduser()
|
|
249
|
+
else:
|
|
250
|
+
install_path = project_dir / config["path"]
|
|
251
|
+
already_installed = install_path.exists() or install_path.is_symlink()
|
|
252
|
+
|
|
253
|
+
results.append({
|
|
254
|
+
"platform": name,
|
|
255
|
+
"name": config["name"],
|
|
256
|
+
"type": config["type"],
|
|
257
|
+
"detected": detected,
|
|
258
|
+
"reason": reason,
|
|
259
|
+
"already_installed": already_installed
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
return results
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def auto_init(project_dir=None):
|
|
266
|
+
"""Detect platforms and install OneMore for all detected ones.
|
|
267
|
+
|
|
268
|
+
Returns dict with detected platforms, installed platforms, and skipped (already installed).
|
|
269
|
+
"""
|
|
270
|
+
detected = detect_platforms(project_dir)
|
|
271
|
+
installed = []
|
|
272
|
+
skipped = []
|
|
273
|
+
not_detected = []
|
|
274
|
+
|
|
275
|
+
for p in detected:
|
|
276
|
+
if not p["detected"]:
|
|
277
|
+
not_detected.append(p)
|
|
278
|
+
continue
|
|
279
|
+
if p["already_installed"]:
|
|
280
|
+
skipped.append(p)
|
|
281
|
+
continue
|
|
282
|
+
result = init_platform(p["platform"], project_dir=project_dir)
|
|
283
|
+
if result.get("status") == "installed":
|
|
284
|
+
installed.append(p)
|
|
285
|
+
else:
|
|
286
|
+
skipped.append(p)
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
"detected": [p for p in detected if p["detected"]],
|
|
290
|
+
"installed": installed,
|
|
291
|
+
"skipped": skipped,
|
|
292
|
+
"not_detected": not_detected
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def list_platforms():
|
|
297
|
+
"""List all platforms with install status."""
|
|
298
|
+
results = []
|
|
299
|
+
for name, config in PLATFORMS.items():
|
|
300
|
+
path = Path(config["path"]).expanduser() if config["type"] == "global" else Path(config["path"])
|
|
301
|
+
installed = path.exists() or path.is_symlink()
|
|
302
|
+
results.append({
|
|
303
|
+
"platform": name,
|
|
304
|
+
"name": config["name"],
|
|
305
|
+
"type": config["type"],
|
|
306
|
+
"path": config["path"],
|
|
307
|
+
"installed": installed
|
|
308
|
+
})
|
|
309
|
+
return results
|