mapples 0.2.0-beta.5 → 0.2.0-beta.7
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 +42 -0
- package/dist/api/agent.d.ts +84 -0
- package/dist/api/agent.js +92 -0
- package/dist/api/agent.js.map +1 -0
- package/dist/api/client.d.ts +3 -0
- package/dist/api/client.js +2 -0
- package/dist/api/client.js.map +1 -1
- package/dist/api/commit.js +1 -0
- package/dist/api/commit.js.map +1 -1
- package/dist/api/errors.js +4 -2
- package/dist/api/errors.js.map +1 -1
- package/dist/api/objects.d.ts +12 -0
- package/dist/api/objects.js +2 -0
- package/dist/api/objects.js.map +1 -1
- package/dist/commands/agent.d.ts +2 -0
- package/dist/commands/agent.js +76 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/create.js +1 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/impl/adoptImpl.js +3 -0
- package/dist/commands/impl/adoptImpl.js.map +1 -1
- package/dist/commands/impl/agentImpl.d.ts +10 -0
- package/dist/commands/impl/agentImpl.js +349 -0
- package/dist/commands/impl/agentImpl.js.map +1 -0
- package/dist/commands/impl/createImpl.js +19 -0
- package/dist/commands/impl/createImpl.js.map +1 -1
- package/dist/commands/impl/initImpl.js +19 -0
- package/dist/commands/impl/initImpl.js.map +1 -1
- package/dist/commands/impl/syncImpl.js +9 -3
- package/dist/commands/impl/syncImpl.js.map +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/project/agentState.d.ts +24 -0
- package/dist/project/agentState.js +42 -0
- package/dist/project/agentState.js.map +1 -0
- package/dist/project/secret.d.ts +6 -2
- package/dist/project/secret.js +11 -5
- package/dist/project/secret.js.map +1 -1
- package/dist/services/agentInstall.d.ts +35 -0
- package/dist/services/agentInstall.js +180 -0
- package/dist/services/agentInstall.js.map +1 -0
- package/dist/services/agentLease.d.ts +2 -0
- package/dist/services/agentLease.js +32 -0
- package/dist/services/agentLease.js.map +1 -0
- package/dist/services/clientFactory.d.ts +2 -0
- package/dist/services/clientFactory.js +16 -1
- package/dist/services/clientFactory.js.map +1 -1
- package/dist/services/scaffold.js +4 -0
- package/dist/services/scaffold.js.map +1 -1
- package/dist/services/syncEngine.js +51 -18
- package/dist/services/syncEngine.js.map +1 -1
- package/dist/style/theme.js +17 -1
- package/dist/style/theme.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/templates/app.json +0 -1
- package/templates/claude/CLAUDE.md +7 -0
- package/templates/claude/mapples.md +118 -0
- package/templates/claude/mcp.json +11 -0
- package/templates/claude/skills/mapples-conventions/SKILL.md +136 -0
- package/templates/claude/skills/mapples-design/SKILL.md +218 -0
- package/templates/claude/skills/mapples-design/reference/component-library.md +128 -0
- package/templates/claude/skills/mapples-design/reference/design-tokens.md +132 -0
- package/templates/claude/skills/mapples-design/reference/layout-contract.md +227 -0
- package/templates/claude/skills/mapples-design/reference/lint-checklist.md +51 -0
- package/templates/claude/skills/mapples-design/reference/plan.md +95 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/empty-states.md +14 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/forms-and-auth.md +22 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/home-dashboard.md +14 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/list-and-detail.md +18 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/microcopy.md +20 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/navigation-chrome.md +21 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/onboarding-flow.md +15 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/screen-flow-wiring.md +37 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/settings-profile.md +16 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/stats-and-progress.md +17 -0
- package/templates/claude/skills/mapples-design/reference/playbooks/visual-hierarchy.md +18 -0
- package/templates/claude/skills/mapples-design/reference/style-guides.md +92 -0
- package/templates/claude/skills/mapples-sync/SKILL.md +93 -0
- package/templates/gitignore +2 -0
- package/templates/package.json +12 -10
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mapples-conventions
|
|
3
|
+
description: How Mapples-managed files are written — file layout, $sid rules, $actions/$data/$refs, the @mapples/ui vs @mapples/components import table, token strings and Styler dictionaries. Use whenever editing a route file, mapples/pages, mapples/components or mapples/theme.ts in a Mapples-linked Expo app.
|
|
4
|
+
---
|
|
5
|
+
<!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
|
|
6
|
+
# Mapples conventions
|
|
7
|
+
|
|
8
|
+
Read `.claude/mapples.md` first (the summary). This skill is the reference.
|
|
9
|
+
|
|
10
|
+
## File layout
|
|
11
|
+
|
|
12
|
+
| File | Role | Editable |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| `__ROUTES_DIR__/<segment>.tsx`, `__ROUTES_DIR__/(group)/<segment>.tsx` | a screen that is in the navigation; `index.tsx` is the section's first screen | yes — merged with Creator |
|
|
15
|
+
| `__ROUTES_DIR__/**/_layout.tsx` | the navigator (Stack/Tabs/Drawer); regenerated from Creator's navigation on every sync | **no** (handshake only, below) |
|
|
16
|
+
| `__PAGES_DIR__/<Name>.tsx` | a screen not (yet) in the navigation; moves into the routes dir when placed | yes |
|
|
17
|
+
| `__COMPONENTS_DIR__/<Name>.tsx` | a reusable Creator component; instances are `import X from '…/<Name>'` + `<X styled />` | yes |
|
|
18
|
+
| `mapples/theme.ts` | design tokens (`theme`, `typography`, `sizing`) | yes — merged per key |
|
|
19
|
+
| `mapples/assets/`, `mapples/assetMap.ts` | Creator assets | **no** |
|
|
20
|
+
| `mapples/sid.d.ts` | types for the `$sid`/`$refs`/`$data`/`$actions`/`$fallback` attributes | no |
|
|
21
|
+
| `.mapples/` | config, secret, head, base, pages.json, components.json, outbox, agent.json | **no** |
|
|
22
|
+
| `_depr_<ts>_<name>.tsx.old` | your version of a file the CLI had to regenerate | read, never restore |
|
|
23
|
+
|
|
24
|
+
The route marker `// mapples-route: <id> — “<Name>”` on line 1 of a route file is the route's
|
|
25
|
+
identity: keep it verbatim. Renaming the file renames the route in Creator.
|
|
26
|
+
|
|
27
|
+
## `$sid`
|
|
28
|
+
|
|
29
|
+
- `$sid="nd_…"` is the canvas node id. Opaque: never parse beyond the prefix, never invent,
|
|
30
|
+
never renumber, never copy to another element, never reuse a deleted one.
|
|
31
|
+
- New elements carry **no** `$sid`. `npx -y mapples@__CLI_VERSION__ sync` tags them (report: `tagged N new element(s)`)
|
|
32
|
+
and rewrites the file with the ids — re-read the file after a sync before editing again.
|
|
33
|
+
- Wrapping an existing element (moving it inside a new `View`) keeps its `$sid`; the sync sees a
|
|
34
|
+
move. Removing an element with a `$sid` deletes it in Creator.
|
|
35
|
+
- `$fallback={{ w, h }}` sits on `Custom` nodes (a non-Mapples component the canvas cannot
|
|
36
|
+
render); leave it as the CLI wrote it.
|
|
37
|
+
|
|
38
|
+
## Transient attributes
|
|
39
|
+
|
|
40
|
+
| Attribute | Shape | Meaning |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| `$actions` | `{ onPress: { type: 'mapples:navigate', staticData: { pageUuid: '<uuid>' } } }` | Creator prototype connection on that event. Other action types (`mapples:setState`, `mapples:goBack`, `mapples:switchTab`) exist; navigate is the one you write. |
|
|
43
|
+
| `$data` | `{ visible: { key: 'vars.sheetOpen', active: true } }` | a data binding of a prop to a project variable — only when the project already has the variable |
|
|
44
|
+
| `$refs` | `{ source: 'ref(image:<uuid>)' }` | a Creator asset reference — Creator-side; never invent one |
|
|
45
|
+
|
|
46
|
+
`pageUuid` lookup: `.mapples/pages.json` maps `pageId → { file, name, route, routeId }`; the
|
|
47
|
+
uuid the action needs is the `uuid` field of `.mapples/base/pages/<pageId>.json`. Both are
|
|
48
|
+
rewritten by every sync — read them fresh.
|
|
49
|
+
|
|
50
|
+
## Imports
|
|
51
|
+
|
|
52
|
+
`@mapples/ui` — primitives (the canvas' base element types):
|
|
53
|
+
|
|
54
|
+
`View`, `Container`, `SafeAreaView`, `ScrollView`, `HorizontalScrollView`, `FlatList`,
|
|
55
|
+
`GridTwoColumns`, `GridThreeColumns`, `GridFourColumns`, `GradientBackground`,
|
|
56
|
+
`ImageBackgroundView`, `Typography`, `Text` (never on a screen — use Typography), `Image`,
|
|
57
|
+
`Icon`, `Svg`, `Vector`, `Video`, `QRCode`, `BarCode`, `Pressable`, `IconButton`, `TextInput`,
|
|
58
|
+
`Select`, `FormView`, `TextField`, `SubmitButton`.
|
|
59
|
+
|
|
60
|
+
`@mapples/components` — the themed library (paints itself from the tokens; prefer it):
|
|
61
|
+
|
|
62
|
+
| Group | Types |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| actions | `Button`, `ButtonGroup`, `Fab`, `TextLink`, `BottomActionBar` |
|
|
65
|
+
| input | `InputField`, `SelectField`, `Checkbox`, `RadioGroup`, `Switch`, `Slider`, `NumberStepper`, `PinInput`, `SearchBar`, `ChatComposer`, `SegmentedControl`, `Rating`, `ChipGroup`, `Chip` |
|
|
66
|
+
| content | `Card`, `MediaCard`, `List`, `ListItem`, `SectionHeader`, `Divider`, `Avatar`, `AvatarGroup`, `Badge`, `StatTile`, `Table`, `Timeline`, `ImageCarousel`, `MessageBubble`, `Accordion`, `Skeleton` |
|
|
67
|
+
| navigation | `TopAppBar`, `BottomNavigationBar`, `Tabs`, `Breadcrumbs`, `Steps`, `PageControl` |
|
|
68
|
+
| feedback | `ProgressBar`, `ProgressCircle`, `Spinner`, `Banner`, `Snackbar`, `EmptyState` |
|
|
69
|
+
| overlays | `Dialog`, `BottomSheet`, `ActionSheet` |
|
|
70
|
+
|
|
71
|
+
Anything else you import (a third-party or hand-written component) becomes an opaque `Custom`
|
|
72
|
+
node on the canvas with a `$fallback` size — allowed, but Creator cannot design inside it.
|
|
73
|
+
|
|
74
|
+
`Styler` comes from `@mapples/style`; `router` from `expo-router`.
|
|
75
|
+
|
|
76
|
+
## Styling
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
<View styled={{ style: styles.row }}>
|
|
80
|
+
<Icon iconName="checkmark-circle" styled={{ styleSvg: styles.icon }} />
|
|
81
|
+
<Typography text="Done" variant="Label" styled={{ styleTypography: styles.done }} />
|
|
82
|
+
</View>
|
|
83
|
+
|
|
84
|
+
const styles = Styler.create({
|
|
85
|
+
row: { flexDirection: 'row', alignItems: 'center', gap: 'sizing.sm' },
|
|
86
|
+
icon: { width: 20, height: 20, color: 'theme.system.success' },
|
|
87
|
+
done: { color: 'theme.text.secondary' },
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- `styled={{ style }}` is the element's own box; `styleTypography` the text of a control
|
|
92
|
+
(Button label, ListItem title); `styleSvg` an Icon's glyph (`color`, `width`, `height`);
|
|
93
|
+
`styleImage` the picture inside an Image; `contentContainerStyle` the scrolling content of a
|
|
94
|
+
ScrollView/FlatList/HorizontalScrollView; `placeholderTextColor` a TextInput's placeholder.
|
|
95
|
+
- One `Styler.create` dictionary per file, below the component; keys say what the element shows
|
|
96
|
+
and is (`signInText`, `heroImage`, `listContent`). A `StyleSheet.create` dictionary is also
|
|
97
|
+
read, but write `Styler.create`.
|
|
98
|
+
- A style may be a single dictionary reference (`styles.card`) or a literal; never an array,
|
|
99
|
+
never a computed expression (Creator cannot read it → `NON_LITERAL_PROP`).
|
|
100
|
+
- Token strings: colors `'theme.<group>.<key>'` (`theme.primary.main`, `theme.primary.contrast`,
|
|
101
|
+
`theme.background.primary`, `theme.background.card`, `theme.text.primary|secondary|tertiary`,
|
|
102
|
+
`theme.neutral.n200`, `theme.system.error`); spacing `'sizing.<key>'` (`xs sm md lg xl
|
|
103
|
+
screenPadding gap radius radiusLarge control card icon`) or `'*N'` (N × base). Gradients take
|
|
104
|
+
literal hex/rgba only.
|
|
105
|
+
- `boxShadow` is an object `{ x, y, radius, color }`, never a CSS string.
|
|
106
|
+
- Library components set their own defaults; change their look through `variant`, `size`,
|
|
107
|
+
`tone` props and the slots — never rebuild one from Views.
|
|
108
|
+
|
|
109
|
+
## Layouts (`_layout.tsx`)
|
|
110
|
+
|
|
111
|
+
The CLI generates every layout from Creator's navigation document. Do not edit or style them
|
|
112
|
+
(header/tab-bar options are set in Creator). To add a **new** section, create the directory
|
|
113
|
+
with a layout whose first line is `// GENERATED by Mapples`:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
// GENERATED by Mapples — this layout is owned by the CLI and regenerated from the navigation document.
|
|
117
|
+
import { Tabs } from 'expo-router';
|
|
118
|
+
|
|
119
|
+
export default function MainLayout() {
|
|
120
|
+
return <Tabs />;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`npx -y mapples@__CLI_VERSION__ sync --yes` then adopts the directory as a tabs navigator (`<Stack>` → stack,
|
|
125
|
+
`<Drawer>` from `expo-router/drawer` → drawer; no layout → stack) and regenerates the file. A
|
|
126
|
+
layout **without** the header is treated as yours and deprecated on the first sync.
|
|
127
|
+
|
|
128
|
+
## What not to do
|
|
129
|
+
|
|
130
|
+
- Do not run `npx -y mapples@__CLI_VERSION__ init`, `npx -y mapples@__CLI_VERSION__ create`, or edit `.mapples/config.json`.
|
|
131
|
+
- Do not restore a `_depr_` file over the regenerated one.
|
|
132
|
+
- Do not hand-write `$sid`s, `$refs`, or navigator options.
|
|
133
|
+
- Do not put JSX children text inside `Typography` (`text` prop only), and do not use `Text`.
|
|
134
|
+
- Do not spread props or map arrays into JSX inside a managed element tree — Creator reads
|
|
135
|
+
literal trees; put dynamic lists behind a `FlatList`/`List` with literal `items` where
|
|
136
|
+
possible, or accept the `NON_LITERAL_PROP` note.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mapples-design
|
|
3
|
+
description: Build a Mapples-linked Expo app from a product brief the way the Creator's in-app AI does — design tokens, an implementation plan, one screen per phase from the design playbooks, wiring and a review — writing route files and mapples/theme.ts and pushing each phase with `npx -y mapples@__CLI_VERSION__ sync` while holding the project's agent lease. Use when the user asks to design, generate or build the app, its screens or its design system.
|
|
4
|
+
argument-hint: "<product brief> [--scope single|minimal|basic|advanced]"
|
|
5
|
+
---
|
|
6
|
+
<!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
|
|
7
|
+
# /mapples-design — build the app from a brief
|
|
8
|
+
|
|
9
|
+
You are the product designer and builder for this app. Your bar is a finished screen a
|
|
10
|
+
designer would ship — not a wireframe. Everything you make is a file in this repo; every phase
|
|
11
|
+
ends with `npx -y mapples@__CLI_VERSION__ sync --yes --json`, which pushes it to Creator where the user watches it land.
|
|
12
|
+
|
|
13
|
+
Read `.claude/mapples.md` and the `mapples-conventions` and `mapples-sync` skills before the
|
|
14
|
+
first file. Reference material for this skill lives next to it:
|
|
15
|
+
|
|
16
|
+
- `reference/style-guides.md` — art directions and style guides (phase 1)
|
|
17
|
+
- `reference/design-tokens.md` — the `mapples/theme.ts` contract and template (phase 2)
|
|
18
|
+
- `reference/plan.md` — scopes and the implementation plan (phase 3)
|
|
19
|
+
- `reference/layout-contract.md` — the rules every screen obeys (phases 5…)
|
|
20
|
+
- `reference/component-library.md` — what to reach for, by need
|
|
21
|
+
- `reference/lint-checklist.md` — the review pass (phase N)
|
|
22
|
+
- `reference/playbooks/<name>.md` — screen-kind playbooks, loaded per screen
|
|
23
|
+
|
|
24
|
+
## Preconditions
|
|
25
|
+
|
|
26
|
+
1. `.mapples/config.json` must exist (the app is linked). If not: stop and ask the user to run
|
|
27
|
+
`npx -y mapples@__CLI_VERSION__ init --secret <key> --agent claude` — never run it yourself.
|
|
28
|
+
2. `npx -y mapples@__CLI_VERSION__ agent status --json`. If `session` is non-null with `status: "active"` and
|
|
29
|
+
`holdsLease` is false, another agent is working on this project: stop and ask whether to take
|
|
30
|
+
over (`--takeover` disconnects it). Never take over silently.
|
|
31
|
+
3. `npx -y mapples@__CLI_VERSION__ sync --yes --json` — be current before designing. Exit 2 here means the repo already
|
|
32
|
+
had conflicts: resolve them (see `mapples-sync`) before going on.
|
|
33
|
+
4. Read `mapples/design.md` if it exists: a previous run's brief, chosen style and plan. Resume
|
|
34
|
+
from the first phase whose output is missing rather than redoing everything.
|
|
35
|
+
|
|
36
|
+
## Steps and the lease
|
|
37
|
+
|
|
38
|
+
The run is one agent session. Steps have a **fixed index convention** shared with Creator's
|
|
39
|
+
progress log:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
0 Brief · 1 Style guides · 2 Design tokens · 3 Plan · 4 Scaffold navigation & screens ·
|
|
43
|
+
5…N-2 one per plan step ("Build the Home screen", …) · N-1 Wiring · N Review
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Start the session as soon as the brief and scope are known, pre-declaring every step title:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx -y mapples@__CLI_VERSION__ agent start --label "Claude Code" --steps "Brief,Style guides,Design tokens,Plan,Scaffold navigation & screens" --json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Exit 4 = busy (see precondition 2). After the plan exists (phase 3), the remaining titles are
|
|
53
|
+
declared as they run: `npx -y mapples@__CLI_VERSION__ agent step --index 5 --title "Build the Home screen" --status running`
|
|
54
|
+
creates the step. Wrap **every** phase:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx -y mapples@__CLI_VERSION__ agent step --index <i> --title "<title>" --status running --json
|
|
58
|
+
# … the work …
|
|
59
|
+
npx -y mapples@__CLI_VERSION__ agent step --index <i> --title "<title>" --status done --detail "<one line>" --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Exit 3 from any `agent` or `sync` command = the lease is gone (Creator disconnected you or the
|
|
63
|
+
lease expired). Stop immediately, do not sync again, and tell the user what was finished.
|
|
64
|
+
|
|
65
|
+
Always end the run — success or not:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx -y mapples@__CLI_VERSION__ agent stop --status done --json
|
|
69
|
+
npx -y mapples@__CLI_VERSION__ agent stop --status failed --error "<what blocked the run>" --json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A phase's syncs are labelled with the running step in Creator's history automatically.
|
|
73
|
+
|
|
74
|
+
## Phase 0 — Brief and scope
|
|
75
|
+
|
|
76
|
+
Input: `$ARGUMENTS` (the brief, optionally `--scope single|minimal|basic|advanced`). If the
|
|
77
|
+
brief is missing or too thin to name the audience, the core value and the mood, ask **one**
|
|
78
|
+
round of questions (AskUserQuestion) — audience, the one thing the app must do well, the
|
|
79
|
+
feeling it should have, and the scope if absent (default `basic`). Then write
|
|
80
|
+
`mapples/design.md`:
|
|
81
|
+
|
|
82
|
+
```md
|
|
83
|
+
# <App name>
|
|
84
|
+
## Brief
|
|
85
|
+
<the brief, cleaned up, 3–8 lines: audience, core value, mood, must-haves, non-goals>
|
|
86
|
+
## Scope
|
|
87
|
+
<single|minimal|basic|advanced> — <one line why>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Report the step done with the scope in `--detail`.
|
|
91
|
+
|
|
92
|
+
## Phase 1 — Style guides
|
|
93
|
+
|
|
94
|
+
Follow `reference/style-guides.md`: propose 3 art directions **for this product**, then 3
|
|
95
|
+
compact style guides. Show them to the user as a table (name, direction, palette swatches as
|
|
96
|
+
hex, headline/body fonts, radius, elevation language, one don't) and ask which one — or accept
|
|
97
|
+
the user's pick from the brief. Append the chosen guide to `design.md` under `## Style guide`.
|
|
98
|
+
|
|
99
|
+
## Phase 2 — Design tokens
|
|
100
|
+
|
|
101
|
+
Follow `reference/design-tokens.md` exactly: write `mapples/theme.ts` (create it — a missing
|
|
102
|
+
file and an empty project is a no-op, so the file is what pushes the tokens). Then
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx -y mapples@__CLI_VERSION__ sync --yes --json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Assert: `exitCode` 0, `pushedOps` ≥ 3 (Theme, Typography, Sizing updates) and no
|
|
109
|
+
`conflicts`. If `pushedOps` is 0, the file did not parse as three literal exports — fix the
|
|
110
|
+
file, do not move on. Record the token summary (primary, background, fonts, radius) in
|
|
111
|
+
`design.md` under `## Tokens`.
|
|
112
|
+
|
|
113
|
+
## Phase 3 — Plan
|
|
114
|
+
|
|
115
|
+
Follow `reference/plan.md`: decisions, navigation (sections → screens), entry screen, ordered
|
|
116
|
+
build steps. Append it to `design.md` under `## Plan` **and** declare the remaining steps:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx -y mapples@__CLI_VERSION__ agent step --index 5 --title "<plan step 1 title>" --status pending --json
|
|
120
|
+
…
|
|
121
|
+
npx -y mapples@__CLI_VERSION__ agent step --index <N-1> --title "Wiring" --status pending --json
|
|
122
|
+
npx -y mapples@__CLI_VERSION__ agent step --index <N> --title "Review" --status pending --json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Show the plan to the user in 6–10 lines; continue unless they object.
|
|
126
|
+
|
|
127
|
+
## Phase 4 — Scaffold navigation and screens
|
|
128
|
+
|
|
129
|
+
Read `.mapples/config.json` for `routesDir` (`__ROUTES_DIR__` here). Then, for the plan's
|
|
130
|
+
navigation:
|
|
131
|
+
|
|
132
|
+
- The root layout already exists and is CLI-owned — leave it.
|
|
133
|
+
- One directory per section: `<routesDir>/(<section-slug>)/` with a `_layout.tsx` whose first
|
|
134
|
+
line is `// GENERATED by Mapples` and whose body renders `<Stack />`, `<Tabs />` (from
|
|
135
|
+
`expo-router`) or `<Drawer />` (from `expo-router/drawer`) per the section's type. This header
|
|
136
|
+
is the handshake: the CLI adopts the navigator kind from it and owns the file from then on.
|
|
137
|
+
- One **minimal** route file per screen: `index.tsx` for the section's first screen, `<slug>.tsx`
|
|
138
|
+
for the rest — a `View` with one `Typography` (`variant="Headline"`, the screen name). Real
|
|
139
|
+
content comes per screen later; the scaffold only mints ids. When the plan has a single
|
|
140
|
+
section, put its files at the root of the routes dir instead of a group.
|
|
141
|
+
- Do not write to `.mapples/`, do not touch the root `_layout.tsx`, do not create pages under
|
|
142
|
+
`pagesDir`.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx -y mapples@__CLI_VERSION__ sync --yes --json
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Assert no conflicts, then read `.mapples/pages.json`: every scaffolded file must be a value's
|
|
149
|
+
`file` with a `routeId`. Note the `pageId` per screen; the `uuid` for `$actions` is in
|
|
150
|
+
`.mapples/base/pages/<pageId>.json`. Screens now exist as empty pages in Creator. Re-read each
|
|
151
|
+
route file — the CLI added the `// mapples-route:` marker and `$sid`s.
|
|
152
|
+
|
|
153
|
+
Navigator and route options (headers, tab icons, initial route, modal presentation) are set in
|
|
154
|
+
Creator, not from code, in this version: describe the intended chrome in `design.md` under
|
|
155
|
+
`## Navigation chrome` so the user can apply it.
|
|
156
|
+
|
|
157
|
+
## Phases 5…N-2 — one screen step at a time
|
|
158
|
+
|
|
159
|
+
For each plan step, in order:
|
|
160
|
+
|
|
161
|
+
1. `agent step … --status running`.
|
|
162
|
+
2. Load the matching playbook(s) from `reference/playbooks/` (read the file; once per run):
|
|
163
|
+
`onboarding-flow`, `home-dashboard`, `list-and-detail`, `forms-and-auth`, `empty-states`,
|
|
164
|
+
`stats-and-progress`, `settings-profile`, `navigation-chrome`; `visual-hierarchy` and
|
|
165
|
+
`microcopy` with the first screen step.
|
|
166
|
+
3. Re-read the route file. Write the **whole screen** in one edit: keep the marker line, keep
|
|
167
|
+
every existing `$sid` on the element it is on, add none. Obey `reference/layout-contract.md`
|
|
168
|
+
and the chosen style guide's instructions (they outrank the contract where they differ).
|
|
169
|
+
Real copy from the brief; picsum photos in every hero/featured/thumb slot.
|
|
170
|
+
4. `npx -y mapples@__CLI_VERSION__ sync --yes --json`. Assert `exitCode` 0; read `warnings` and fix what is yours
|
|
171
|
+
(NON_LITERAL_PROP on a value you can make literal, UNKNOWN_ELEMENT). Exit 2 → resolve per
|
|
172
|
+
`mapples-sync`, sync again.
|
|
173
|
+
5. Re-read the file (it now carries `$sid`s), run it through `reference/lint-checklist.md`
|
|
174
|
+
mentally, fix, sync again if you changed anything.
|
|
175
|
+
6. `agent step … --status done --detail "<screen>: <what it shows>"`.
|
|
176
|
+
|
|
177
|
+
Two screens in one plan step: do them one after the other inside the step, syncing after each.
|
|
178
|
+
|
|
179
|
+
## Phase N-1 — Wiring
|
|
180
|
+
|
|
181
|
+
Load `playbooks/screen-flow-wiring.md`. For every navigation the plan names, add to the source
|
|
182
|
+
element's primary event both the Creator connection and the runtime handler:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
<Button
|
|
186
|
+
label="Get started"
|
|
187
|
+
variant="filled"
|
|
188
|
+
size="lg"
|
|
189
|
+
fullWidth
|
|
190
|
+
onPress={() => router.push('/(main)')}
|
|
191
|
+
$actions={{ onPress: { type: 'mapples:navigate', staticData: { pageUuid: '<uuid from base>' } } }}
|
|
192
|
+
/>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
(`import { router } from 'expo-router'`.) Rows and cards use their own `onPress`. Walk the golden
|
|
196
|
+
path from the entry screen; every screen reachable, every flow with an exit. Sync; the report's
|
|
197
|
+
`pushedOps` must cover every action you added.
|
|
198
|
+
|
|
199
|
+
## Phase N — Review
|
|
200
|
+
|
|
201
|
+
Load `reference/lint-checklist.md`. For every screen: re-read the file, check each item, fix.
|
|
202
|
+
Then `npx -y mapples@__CLI_VERSION__ doctor --json` (no `duplicate`/`missing` issues; `drift` is fine before the final
|
|
203
|
+
sync) and a final `npx -y mapples@__CLI_VERSION__ sync --yes --json` with exit 0. Update `design.md` with a `## Status`
|
|
204
|
+
line (screens built, what was cut, the one decision the user may want to change). Then
|
|
205
|
+
`npx -y mapples@__CLI_VERSION__ agent stop --status done`.
|
|
206
|
+
|
|
207
|
+
Reply to the user in 3–5 lines: what was built, where to look in Creator, the one decision to
|
|
208
|
+
revisit. No headings.
|
|
209
|
+
|
|
210
|
+
## Working style
|
|
211
|
+
|
|
212
|
+
- One screen, one edit — never element by element across many edits (each sync tags ids; many
|
|
213
|
+
partial syncs mean many rewrites).
|
|
214
|
+
- After every sync, re-read before editing. Never keep a stale copy of a file in your head.
|
|
215
|
+
- Prefer fewer screens fully designed over more screens sketched.
|
|
216
|
+
- Ask only when a product decision is genuinely ambiguous; otherwise decide, state it in
|
|
217
|
+
`design.md`, move on.
|
|
218
|
+
- Never emoji. Never lorem ipsum. Never `Text`. Never a hand-written `$sid`.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
|
|
2
|
+
# Component library — what to reach for
|
|
3
|
+
|
|
4
|
+
Two packages, one canvas. Everything below is a registered canvas type: Creator renders it,
|
|
5
|
+
its style panel edits it, and `npx -y mapples@__CLI_VERSION__ sync` round-trips it. Import primitives from
|
|
6
|
+
`@mapples/ui`, the themed library from `@mapples/components`. Anything else you import is an
|
|
7
|
+
opaque `Custom` node (allowed, but Creator cannot design inside it).
|
|
8
|
+
|
|
9
|
+
## `@mapples/ui` — primitives
|
|
10
|
+
|
|
11
|
+
| Type | Use | Notes |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `Container` | the screen root or a flex: 1 region | full-size column by default |
|
|
14
|
+
| `View` | any column/row | width 100% in a column; content-sized in a row |
|
|
15
|
+
| `SafeAreaView` | root that respects the notch | or paddingTop ≥ 48 on the root |
|
|
16
|
+
| `ScrollView` | vertical scrolling content | spacing in `styled.contentContainerStyle` |
|
|
17
|
+
| `HorizontalScrollView` | a rail of cards | full-bleed; `contentContainerStyle: { gap: 12, paddingHorizontal: 20 }` |
|
|
18
|
+
| `FlatList` | long uniform lists | prefer `List` + `ListItem` for designed rows |
|
|
19
|
+
| `GridTwoColumns` / `GridThreeColumns` / `GridFourColumns` | tile grids | children tile automatically |
|
|
20
|
+
| `GradientBackground` | the one gradient accent per screen | `gradient` prop with literal hex stops |
|
|
21
|
+
| `ImageBackgroundView` | photo with content over it | `source` + `overflow: 'hidden'` + a scrim child |
|
|
22
|
+
| `Typography` | every piece of text | `text` + `variant` (Headline, Subtitle, Body, Caption, Overline, Button, Link, Label, Code) |
|
|
23
|
+
| `Text` | never on a screen | bypasses the type scale |
|
|
24
|
+
| `Image` | a picture | `source` (picsum URL), `contentFit="cover"`, explicit width/height |
|
|
25
|
+
| `Icon` | a glyph from the project icon family | `iconName`; color/size in `styled.styleSvg` |
|
|
26
|
+
| `IconButton` | icon-only tap target | `iconName`, `accessibilityLabel` (required), `badgeCount` |
|
|
27
|
+
| `Pressable` | a custom tappable region | only when no library control fits |
|
|
28
|
+
| `TextInput` | raw input | in forms use `InputField` instead |
|
|
29
|
+
| `Select` | raw select | in forms use `SelectField` instead |
|
|
30
|
+
| `Svg` / `Vector` / `Video` / `QRCode` / `BarCode` | media specials | as needed |
|
|
31
|
+
| `FormView` / `TextField` / `SubmitButton` | form primitives | the library's `InputField`/`Button` are the designed versions |
|
|
32
|
+
|
|
33
|
+
## `@mapples/components` — the themed library
|
|
34
|
+
|
|
35
|
+
Library types paint themselves from the tokens; change their look through `variant`, `size`
|
|
36
|
+
and `tone` props and the style slots — never rebuild one from Views. Array props (`options`,
|
|
37
|
+
`items`, `columns`) are literal arrays.
|
|
38
|
+
|
|
39
|
+
### actions
|
|
40
|
+
|
|
41
|
+
| Type | Props to know | Use |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `Button` | `label`, `variant` filled\|outlined\|text\|tonal, `size` sm\|md\|lg, `fullWidth`, `leadingIconName`, `tone` | the primary action (filled lg fullWidth), secondary actions (outlined/text) |
|
|
44
|
+
| `ButtonGroup` | `options` [{label, value}], `value` | a segmented pair of actions |
|
|
45
|
+
| `Fab` | `iconName`, `accessibilityLabel`, `label`, `extended` | one floating primary action |
|
|
46
|
+
| `TextLink` | `label`, `tone`, `underline` | Skip, Forgot password?, Sign in |
|
|
47
|
+
| `BottomActionBar` | `sticky`; children | the sticky bar holding price + CTA on detail/checkout screens |
|
|
48
|
+
|
|
49
|
+
### input
|
|
50
|
+
|
|
51
|
+
| Type | Props to know | Use |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| `InputField` | `label`, `placeholder`, `helperText`, `errorText`, `leadingIconName`, `keyboardType`, `autoCapitalize`, `secureTextEntry`, `showPasswordToggle`, `variant` outlined\|filled | every text field in a form |
|
|
54
|
+
| `SelectField` | `label`, `options`, `placeholder`, `value` | dropdowns |
|
|
55
|
+
| `Checkbox` | `label`, `value` | yes/no that lists |
|
|
56
|
+
| `RadioGroup` | `options`, `value` | one exclusive choice |
|
|
57
|
+
| `Switch` | `label`, `value` | a toggle |
|
|
58
|
+
| `Slider` | `min`, `max`, `value`, `showValue` | a range |
|
|
59
|
+
| `NumberStepper` | `min`, `max`, `value` | quantity |
|
|
60
|
+
| `PinInput` | `length` | one-time codes |
|
|
61
|
+
| `SearchBar` | `placeholder`, `value` | search (a filled pill by default) |
|
|
62
|
+
| `ChatComposer` | `placeholder`, `leadingIconName` | the chat input pinned to the bottom |
|
|
63
|
+
| `SegmentedControl` | `options`, `value` | switching a view mode |
|
|
64
|
+
| `Rating` | `value`, `max`, `readOnly` | stars |
|
|
65
|
+
| `ChipGroup` | `options` [{label, value, iconName?}], `value`, `variant` filter\|choice, `scrollable` | filters and tags |
|
|
66
|
+
| `Chip` | `label`, `variant` assist\|filter\|suggestion, `selected` | a single tag (content-sized; inside a row) |
|
|
67
|
+
|
|
68
|
+
### content
|
|
69
|
+
|
|
70
|
+
| Type | Props to know | Use |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| `Card` | `variant` elevated\|filled\|outlined; children | any surface that groups content |
|
|
73
|
+
| `MediaCard` | `source`, `title`, `subtitle`, `meta`, `aspectRatio` | a photo-topped tile (rails, grids) |
|
|
74
|
+
| `List` | `variant` plain\|inset\|card, `header`; `ListItem` children | rows — the List draws dividers and the surface |
|
|
75
|
+
| `ListItem` | `title`, `subtitle`, `leading` icon\|avatar\|image\|none, `leadingIconName`, `source`, `trailing` chevron\|text\|switch\|checkbox\|none, `trailingText`, `tone` | one row |
|
|
76
|
+
| `SectionHeader` | `title`, `actionLabel` | "Popular · See all" |
|
|
77
|
+
| `Divider` | `inset` | a hairline between groups |
|
|
78
|
+
| `Avatar` | `name` or `source`, `size` sm\|md\|lg\|xl, `badgeCount` | a person |
|
|
79
|
+
| `AvatarGroup` | `items` [{name, source}], `max` | several people |
|
|
80
|
+
| `Badge` | `label` or `count`, `variant` text\|dot\|count, `tone` | a status pill or a count |
|
|
81
|
+
| `StatTile` | `label`, `value`, `unit`, `caption`, `trend`, `trendValue`, `iconName`, `variant` | a KPI |
|
|
82
|
+
| `Table` | `columns` [{key, title}], `rows` | tabular data |
|
|
83
|
+
| `Timeline` | `items` [{title, subtitle, time, status}] | a sequence of events |
|
|
84
|
+
| `ImageCarousel` | `items` [{source, caption}] | swipeable photos |
|
|
85
|
+
| `MessageBubble` | `text`, `direction` in\|out, `time`, `status` | a chat message |
|
|
86
|
+
| `Accordion` | `items` [{title, content}] | FAQ / expandable rows |
|
|
87
|
+
| `Skeleton` | `variant` text\|rect\|circle, `width`, `height` | a loading placeholder |
|
|
88
|
+
|
|
89
|
+
### navigation (in-content)
|
|
90
|
+
|
|
91
|
+
| Type | Props to know | Use |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `TopAppBar` | `title`, `showBack`, `actions` [{iconName, value}], `variant` small\|large | an in-content header ONLY when the stack header is hidden |
|
|
94
|
+
| `BottomNavigationBar` | `items` [{label, iconName, value}], `value` | a single-screen demo of a tab shell — real tabs are a navigator |
|
|
95
|
+
| `Tabs` | `items` [{label, value}], `value` | switching panels inside ONE screen |
|
|
96
|
+
| `Breadcrumbs` | `items` [{label, value}], `separator`, `maxItems` | a path |
|
|
97
|
+
| `Steps` | `items` [{label}], `current` | a multi-step progress |
|
|
98
|
+
| `PageControl` | `count`, `value`, `variant` dots\|bars | onboarding page dots |
|
|
99
|
+
|
|
100
|
+
### feedback
|
|
101
|
+
|
|
102
|
+
| Type | Props to know | Use |
|
|
103
|
+
| --- | --- | --- |
|
|
104
|
+
| `ProgressBar` | `value`, `max`, `showLabel` | a goal or an upload |
|
|
105
|
+
| `ProgressCircle` | `value`, `size`, `showLabel` | a ring |
|
|
106
|
+
| `Spinner` | `size` | loading |
|
|
107
|
+
| `Banner` | `title`, `message`, `tone`, `actionLabel` | an inline notice |
|
|
108
|
+
| `Snackbar` | `message`, `actionLabel`, `visible` | a toast (last in the root, `visible={false}` unless bound) |
|
|
109
|
+
| `EmptyState` | `iconName` or `imageSource`, `title`, `message`, `actionLabel`, `secondaryActionLabel`, `tone` | nothing to show |
|
|
110
|
+
|
|
111
|
+
### overlays (last in the page root; `visible={false}` unless bound to a variable)
|
|
112
|
+
|
|
113
|
+
| Type | Props to know | Use |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| `Dialog` | `title`, `message`, `primaryActionLabel`, `secondaryActionLabel`, `tone`, `visible` | a confirmation |
|
|
116
|
+
| `BottomSheet` | `title`, `visible`; children | a picker or a quick detail |
|
|
117
|
+
| `ActionSheet` | `options` [{label, value, iconName?, destructive?}], `visible` | a list of actions |
|
|
118
|
+
|
|
119
|
+
## Style slots
|
|
120
|
+
|
|
121
|
+
`styled={{ style, styleTypography, styleSvg, styleImage, contentContainerStyle, placeholderTextColor }}` —
|
|
122
|
+
`style` is the element's box; `styleTypography` its text (Button label, ListItem title, StatTile
|
|
123
|
+
value); `styleSvg` its glyph; `contentContainerStyle` the scrolling content. Library components
|
|
124
|
+
expose the same slots; use them for one-off tweaks (a card's `gap`, a rail's padding) and
|
|
125
|
+
props for everything the component already knows how to do.
|
|
126
|
+
|
|
127
|
+
> Prop names above follow the Creator's component digest; when unsure, keep to the ones listed
|
|
128
|
+
> here — an unknown prop is ignored (and reported by the Creator lint as `unknown-prop`).
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<!-- GENERATED by Mapples __CLI_VERSION__ — re-run npx -y mapples@__CLI_VERSION__ agent install --force to refresh -->
|
|
2
|
+
# Design tokens (phase 2) — `mapples/theme.ts`
|
|
3
|
+
|
|
4
|
+
Ported from the Creator's full-variant generation (`generate.ts` `variantSystem` +
|
|
5
|
+
`schemas.ts` `designVariantSchema`). The output is a file, not a JSON reply: `mapples/theme.ts`
|
|
6
|
+
exports three **literal** objects — `theme`, `typography`, `sizing` — and `npx -y mapples@__CLI_VERSION__ sync` pushes
|
|
7
|
+
them as the project's Theme, Typography and Sizing documents.
|
|
8
|
+
|
|
9
|
+
## Rules
|
|
10
|
+
|
|
11
|
+
Act as a senior product designer building a design system for this mobile app. The user
|
|
12
|
+
already chose a style guide. Realize EXACTLY this style — same palette family (the preview
|
|
13
|
+
colors are anchors to build around), same fonts, same shape language, same iconFamily.
|
|
14
|
+
|
|
15
|
+
- Colors are hex. Provide BOTH light and dark maps; dark is a real dark design (dark surfaces,
|
|
16
|
+
lighter text), not an inversion. `primary.main` must have ≥ 4.5:1 contrast against
|
|
17
|
+
`primary.contrast`; `text.primary` against `background.primary` likewise. `neutral` runs
|
|
18
|
+
white→n50…n900→black as a smooth ramp in the theme's hue bias.
|
|
19
|
+
- Fonts come ONLY from the library in `style-guides.md` (family + weight); body fonts must be
|
|
20
|
+
sans or a highly legible serif. `fontFamily` values are the registered names
|
|
21
|
+
`"<Family>-<Weight>"` (`"Manrope-SemiBold"`) with `fontWeight` matching the weight (Regular
|
|
22
|
+
400, Medium 500, SemiBold 600, Bold 700). Never "system", "Helvetica" or any other name: it
|
|
23
|
+
will not render.
|
|
24
|
+
- The type scale is for a phone: Headline 26–34, Subtitle 18–22, Body 15–17, Caption 12–13,
|
|
25
|
+
Overline 10–12, Button 15–17, Link = Body, Code 13–14, Label 13–15. `lineHeight` ≈ 1.25× for
|
|
26
|
+
headlines, 1.5× for body. Headline and Subtitle share the headline font; Body, Caption, Label,
|
|
27
|
+
Link share the body font; Button and Overline share the button font; Code uses the mono font.
|
|
28
|
+
Overline is `textTransform: 'uppercase'`.
|
|
29
|
+
- Sizing: `base` 4; `xs/sm/md/lg/xl` a clear scale (4/8/12–16/24/32), `screenPadding` 16–24,
|
|
30
|
+
`gap` 12–16, `radius` and `radiusLarge` to fit the direction (sharp directions near 0, soft
|
|
31
|
+
ones 16–28; `radiusLarge` ≥ `radius`), `control` 44–56, `card` 16–24, `icon` 20–28. All
|
|
32
|
+
multiples of `base`.
|
|
33
|
+
- `instructions` (write them into `design.md` under `## Design instructions`, not into the
|
|
34
|
+
file): 150–300 words of concrete rules for every future screen — voice and copy tone, spacing
|
|
35
|
+
rules, component style (buttons, cards, inputs, lists), imagery and icon treatment, motion,
|
|
36
|
+
explicit do / don't lists. They MUST state the elevation language as a deliberate choice —
|
|
37
|
+
flat ("1px borders / contrasting surfaces, no shadows") is a first-class option and the right
|
|
38
|
+
one for calm, minimal, editorial or brutalist directions; when shadows are chosen, give the
|
|
39
|
+
exact soft recipe (offsets, blur ≥ 3× offset, rgba alpha ≤ 0.12) AND name the surfaces it
|
|
40
|
+
applies to plus where shadows are forbidden (inputs, chips, in-card rows). Also state the
|
|
41
|
+
corner-radius system (which radius which surface gets, including any top-only/bottom-only
|
|
42
|
+
corner rules for sheets and heroes), where a gradient accent is allowed (if anywhere), and the
|
|
43
|
+
imagery/placeholder style. Written for a designer who has never seen the product.
|
|
44
|
+
|
|
45
|
+
## Bounds (the schema; a value outside them is a contract violation)
|
|
46
|
+
|
|
47
|
+
- hex: `#rrggbb` or `#rrggbbaa`
|
|
48
|
+
- text scale: `fontSize` 10–48 int, `lineHeight` 12–60 int, `letterSpacing` −2…3
|
|
49
|
+
- sizing: `base` 2–8; `xs` 2–12, `sm` 4–16, `md` 8–24, `lg` 16–40, `xl` 24–64,
|
|
50
|
+
`screenPadding` 12–32, `gap` 8–24, `radius` 0–24, `radiusLarge` 0–40, `control` 40–64,
|
|
51
|
+
`card` 12–32, `icon` 16–32 — all ints
|
|
52
|
+
|
|
53
|
+
## The file — copy this shape exactly, fill every value
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// mapples/theme.ts — design tokens, synced with Creator by `npx -y mapples@__CLI_VERSION__ sync`.
|
|
57
|
+
// Edit values freely; keys you add here are pushed to the canvas style config.
|
|
58
|
+
|
|
59
|
+
export const theme = {
|
|
60
|
+
variant: 'auto',
|
|
61
|
+
defaultColor: '#1B1B1F', // = light.text.primary
|
|
62
|
+
light: {
|
|
63
|
+
background: { primary: '#FFFFFF', card: '#F7F7F9', contrast: '#1B1B1F' },
|
|
64
|
+
primary: { main: '#5B4DE0', light: '#8C82F0', dark: '#3D31B5', contrast: '#FFFFFF', background: '#EEECFC' },
|
|
65
|
+
accent: { main: '#F2994A', light: '#F7B980', dark: '#C8792F', contrast: '#1B1B1F', background: '#FDF1E6' },
|
|
66
|
+
text: { primary: '#1B1B1F', secondary: '#5A5B66', tertiary: '#8B8C99' },
|
|
67
|
+
neutral: {
|
|
68
|
+
white: '#FFFFFF', n50: '#F7F7F9', n100: '#EFEFF3', n200: '#E1E1E8', n300: '#C9C9D3',
|
|
69
|
+
n400: '#A6A7B5', n500: '#7F8090', n600: '#5A5B66', n700: '#3F404A', n800: '#2A2B33',
|
|
70
|
+
n900: '#1B1B1F', black: '#000000',
|
|
71
|
+
},
|
|
72
|
+
system: { info: '#2F80ED', success: '#27AE60', warning: '#F2C94C', error: '#EB5757' },
|
|
73
|
+
},
|
|
74
|
+
dark: {
|
|
75
|
+
background: { primary: '#121217', card: '#1C1C24', contrast: '#F5F5FA' },
|
|
76
|
+
primary: { main: '#8C82F0', light: '#B1AAF6', dark: '#5B4DE0', contrast: '#121217', background: '#26224A' },
|
|
77
|
+
accent: { main: '#F7B980', light: '#FAD1A9', dark: '#F2994A', contrast: '#121217', background: '#3A2A1A' },
|
|
78
|
+
text: { primary: '#F5F5FA', secondary: '#B8B9C6', tertiary: '#8B8C99' },
|
|
79
|
+
neutral: {
|
|
80
|
+
white: '#FFFFFF', n50: '#2A2B33', n100: '#3F404A', n200: '#4A4B57', n300: '#5A5B66',
|
|
81
|
+
n400: '#7F8090', n500: '#A6A7B5', n600: '#C9C9D3', n700: '#E1E1E8', n800: '#EFEFF3',
|
|
82
|
+
n900: '#F7F7F9', black: '#000000',
|
|
83
|
+
},
|
|
84
|
+
system: { info: '#5EA0F5', success: '#4CC77F', warning: '#F5D76E', error: '#F27C7C' },
|
|
85
|
+
},
|
|
86
|
+
} as const;
|
|
87
|
+
|
|
88
|
+
export const typography = {
|
|
89
|
+
fontFamily: 'Manrope-Regular', // = the Body font
|
|
90
|
+
color: '#1B1B1F', // = light.text.primary
|
|
91
|
+
default: 'Body',
|
|
92
|
+
typography: {
|
|
93
|
+
Headline: { fontFamily: 'Sora-Bold', fontWeight: '700', fontSize: 30, lineHeight: 38, letterSpacing: -0.5 },
|
|
94
|
+
Subtitle: { fontFamily: 'Sora-SemiBold', fontWeight: '600', fontSize: 20, lineHeight: 26, letterSpacing: -0.2 },
|
|
95
|
+
Body: { fontFamily: 'Manrope-Regular', fontWeight: '400', fontSize: 16, lineHeight: 24, letterSpacing: 0 },
|
|
96
|
+
Caption: { fontFamily: 'Manrope-Regular', fontWeight: '400', fontSize: 13, lineHeight: 18, letterSpacing: 0 },
|
|
97
|
+
Overline: { fontFamily: 'Manrope-SemiBold', fontWeight: '600', fontSize: 11, lineHeight: 16, letterSpacing: 1, textTransform: 'uppercase' },
|
|
98
|
+
Button: { fontFamily: 'Manrope-SemiBold', fontWeight: '600', fontSize: 16, lineHeight: 20, letterSpacing: 0.2 },
|
|
99
|
+
Link: { fontFamily: 'Manrope-Medium', fontWeight: '500', fontSize: 16, lineHeight: 24, letterSpacing: 0 },
|
|
100
|
+
Code: { fontFamily: 'IBMPlexMono-Regular', fontWeight: '400', fontSize: 14, lineHeight: 20, letterSpacing: 0 },
|
|
101
|
+
Label: { fontFamily: 'Manrope-Medium', fontWeight: '500', fontSize: 14, lineHeight: 20, letterSpacing: 0.1 },
|
|
102
|
+
},
|
|
103
|
+
} as const;
|
|
104
|
+
|
|
105
|
+
export const sizing = {
|
|
106
|
+
base: 4,
|
|
107
|
+
sizing: {
|
|
108
|
+
xs: 4, sm: 8, md: 12, lg: 24, xl: 32,
|
|
109
|
+
screenPadding: 20, gap: 12, radius: 12, radiusLarge: 24,
|
|
110
|
+
control: 48, card: 20, icon: 24,
|
|
111
|
+
},
|
|
112
|
+
} as const;
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The values above are an example, not the answer — every project gets its own. Keep the
|
|
116
|
+
comments, the `as const`, the three named exports and no other statements: the CLI parses the
|
|
117
|
+
file as literal objects (an import, a spread or a function call makes the whole file
|
|
118
|
+
unreadable and the sync reports `NON_LITERAL_PROP … local style edits ignored`).
|
|
119
|
+
|
|
120
|
+
## After writing
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npx -y mapples@__CLI_VERSION__ sync --yes --json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Expect `pushedOps` ≥ 3 and `exitCode` 0. The tokens are now the project's; every style token
|
|
127
|
+
string in a screen (`'theme.primary.main'`, `'sizing.md'`) resolves against them. Later edits to
|
|
128
|
+
`mapples/theme.ts` merge per key with edits made in Creator; a same-key conflict deprecates the
|
|
129
|
+
file and regenerates it from Creator — re-apply, never restore.
|
|
130
|
+
|
|
131
|
+
> Not ported (Creator-only): the live token reveal, the review-feedback regeneration loop and
|
|
132
|
+
> the `iconFamily` project setting (set it in Creator: Project → Settings → Icons).
|