figmatk 0.0.7 → 0.0.8

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/lib/api.mjs CHANGED
@@ -1667,12 +1667,15 @@ function parseColor(fd, color) {
1667
1667
  if (typeof color === 'string') {
1668
1668
  // Hex string
1669
1669
  if (/^#?[0-9a-fA-F]{6}$/.test(color)) return _hexToRgb(color);
1670
- // Designer alias (case-insensitive)
1670
+ // Figma theme variable first (exact match, preserves colorVar binding for slides)
1671
+ try {
1672
+ const variable = resolveColorVariable(fd, color);
1673
+ return { r: variable.r, g: variable.g, b: variable.b, _guid: variable.guid };
1674
+ } catch (_) {}
1675
+ // Designer alias fallback (case-insensitive)
1671
1676
  const alias = DESIGNER_COLORS[color.toLowerCase()];
1672
1677
  if (alias) return _hexToRgb(alias);
1673
- // Figma theme variable
1674
- const variable = resolveColorVariable(fd, color);
1675
- return { r: variable.r, g: variable.g, b: variable.b, _guid: variable.guid };
1678
+ throw new Error(`Unknown color: "${color}". Use a Light Slides name ('Black', 'Teal'), a designer alias ('navy', 'coral'), or a hex string ('#E63946').`);
1676
1679
  }
1677
1680
  throw new Error(`Invalid color: ${JSON.stringify(color)}`);
1678
1681
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figmatk",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Figma Toolkit — Swiss-army knife CLI for Figma .deck and .fig files",
5
5
  "type": "module",
6
6
  "bin": {
@@ -5,7 +5,7 @@ description: >
5
5
  create a presentation, build a slide deck, edit slides, update text or images,
6
6
  clone or remove slides, or produce a .deck file for Figma Slides.
7
7
  metadata:
8
- version: "0.0.6"
8
+ version: "0.0.7"
9
9
  ---
10
10
 
11
11
  # FigmaTK Skill
@@ -25,19 +25,50 @@ metadata:
25
25
 
26
26
  Use this when the user wants a new presentation. Write a Node.js script and execute it.
27
27
 
28
+ > **Import path:** `figmatk` is an npm package. Import from the installed package:
29
+ > ```javascript
30
+ > import { Deck } from 'figmatk';
31
+ > ```
32
+
28
33
  ```javascript
29
34
  import { Deck } from 'figmatk';
30
35
 
31
36
  const deck = await Deck.create('My Presentation');
32
- const slide = deck.addBlankSlide();
33
37
 
34
- slide.setBackground('slate');
35
- slide.addText('Slide Title', { style: 'Title', color: 'white', x: 64, y: 80, width: 1792 });
36
- slide.addText('Subtitle or tagline here', { style: 'Body 1', color: 'light-gray', x: 64, y: 240, width: 1200 });
38
+ const slide = deck.addBlankSlide(); // template blank slide auto-removed
39
+ slide.setBackground('Black'); // named color see list below
40
+ slide.addText('Slide Title', {
41
+ style: 'Title', color: 'White',
42
+ x: 64, y: 80, width: 1792, align: 'LEFT'
43
+ });
44
+ slide.addText('Subtitle', {
45
+ style: 'Body 1', color: 'Grey',
46
+ x: 64, y: 240, width: 1200, align: 'LEFT'
47
+ });
37
48
 
38
49
  await deck.save('/path/to/output.deck');
39
50
  ```
40
51
 
52
+ ### ⚠️ Critical gotchas
53
+
54
+ | Issue | Wrong | Right |
55
+ |-------|-------|-------|
56
+ | `setBackground` with hex | `s.setBackground('#1A1A1A')` | `s.setBackground('Black')` |
57
+ | `setBackground` with raw RGB | `s.setBackground({ r:0.1, g:0.1, b:0.1 })` | `s.setBackground('Black')` — raw RGB silently renders white |
58
+ | Shape method signature | `s.addRectangle({ x:0, y:0, width:100 })` | `s.addRectangle(0, 0, 100, 100, opts)` |
59
+ | Shape fill color | `{ fill: '#F4900C' }` | `{ fill: hex('#F4900C') }` — use the hex() helper |
60
+ | `addLine` options | `{ strokeColor: ..., strokeWeight: 2 }` | `{ color: 'Black', weight: 2 }` |
61
+ | `align` value | `align: 'left'` | `align: 'LEFT'` (uppercase) |
62
+
63
+ ### Hex color helper (for shape fills)
64
+
65
+ ```javascript
66
+ function hex(h) {
67
+ return { r: parseInt(h.slice(1,3),16)/255, g: parseInt(h.slice(3,5),16)/255, b: parseInt(h.slice(5,7),16)/255 };
68
+ }
69
+ // Usage: s.addRectangle(0, 0, 200, 50, { fill: hex('#F4900C') })
70
+ ```
71
+
41
72
  ### Text styles
42
73
 
43
74
  | Style | Size | Weight | Use for |
@@ -51,37 +82,33 @@ await deck.save('/path/to/output.deck');
51
82
  | `Body 3` | 24pt | Regular | Captions, labels |
52
83
  | `Note` | 20pt | Regular | Footnotes, sources |
53
84
 
54
- ### Colors
85
+ ### Named colors for `setBackground()`
55
86
 
56
- Use **names** never RGB values. The API accepts:
87
+ > **Case-sensitive.** `'Black'` works, `'black'` does not.
57
88
 
58
- | Type | Example |
59
- |------|---------|
60
- | Designer name | `'teal'`, `'coral'`, `'navy'`, `'midnight'`, `'forest'`, `'charcoal'`, `'cream'`, `'gold'`, `'terracotta'`, `'sage'`, `'cobalt'`, `'rose'`, `'indigo'`, `'burgundy'`, `'sand'`... |
61
- | Hex string | `'#E63946'` |
62
- | Light Slides theme | `'Blue'`, `'Red'`, `'Green'`, `'Yellow'`, `'Orange'`, `'Pink'`, `'Purple'`, `'Slate'`, `'White'`, `'Black'` |
89
+ `'Black'`, `'White'`, `'Grey'`, `'Blue'`, `'Red'`, `'Yellow'`, `'Green'`, `'Orange'`, `'Pink'`, `'Purple'`, `'Teal'`, `'Violet'`, `'Persimmon'`, `'Pale Pink'`, `'Pale Blue'`, `'Pale Green'`, `'Pale Teal'`, `'Pale Purple'`, `'Pale Persimmon'`, `'Pale Violet'`, `'Pale Red'`, `'Pale Yellow'`
63
90
 
64
- Pick colors by feeling: "warm terracotta on cream", "midnight blue with coral accent". Let the design drive the choice, then pick the closest name.
91
+ Use `'Black'` for dark backgrounds, `'White'` for light. For custom slide backgrounds, use the closest named color **not hex**.
65
92
 
66
93
  ### Slide dimensions
67
94
 
68
- 1920 × 1080px. Position and size all elements in pixels.
95
+ 1920 × 1080px. All positions and sizes in pixels.
69
96
 
70
- ### Available slide methods
97
+ ### Slide methods (correct signatures)
71
98
 
72
99
  ```javascript
73
- slide.setBackground(color) // named color or hex
74
- slide.addText(text, opts) // opts: style, color, x, y, width, align, bold, italic, fontSize
75
- slide.addFrame(opts) // auto-layout frame: stackMode, spacing, x, y, width, height
76
- slide.addRectangle(opts) // opts: x, y, width, height, fill, opacity, cornerRadius
77
- slide.addEllipse(opts) // circle/ellipse: x, y, width, height, fill
78
- slide.addDiamond(opts) // diamond shape
79
- slide.addTriangle(opts) // triangle
80
- slide.addStar(opts) // 5-pointed star
81
- slide.addLine(x1, y1, x2, y2, opts) // line: strokeColor, strokeWeight
82
- slide.addImage(path, opts) // freestanding image: x, y, width, height
83
- slide.addTable(data, opts) // 2D array of strings: x, y, width, colWidths, rowHeight
84
- slide.addSVG(x, y, width, svgPathOrBuf, opts) // import SVG vector graphic
100
+ slide.setBackground(namedColor) // named color only hex/raw RGB render white
101
+ slide.addText(text, opts) // opts: style, color (named or hex('#...')), x, y, width, align, bold, italic, fontSize
102
+ slide.addFrame(opts) // auto-layout: stackMode, spacing, x, y, width, height
103
+ slide.addRectangle(x, y, width, height, opts) // opts: fill (named or {r,g,b}), opacity, cornerRadius
104
+ slide.addEllipse(x, y, width, height, opts) // opts: fill, opacity
105
+ slide.addDiamond(x, y, width, height, opts)
106
+ slide.addTriangle(x, y, width, height, opts)
107
+ slide.addStar(x, y, width, height, opts)
108
+ slide.addLine(x1, y1, x2, y2, opts) // opts: color, weight
109
+ slide.addImage(path, opts) // opts: x, y, width, height
110
+ slide.addTable(data, opts) // 2D string array; opts: x, y, width, colWidths, rowHeight
111
+ slide.addSVG(x, y, width, svgPathOrBuf, opts)
85
112
  ```
86
113
 
87
114
  ---
@@ -118,71 +145,60 @@ Use this when the user provides a `.deck` file to modify.
118
145
 
119
146
  ## Design Philosophy
120
147
 
121
- Every deck must look **intentionally designed**, not AI-generated. Follow these rules on every presentation task.
148
+ Every deck must look **intentionally designed**, not AI-generated.
122
149
 
123
150
  ### Colour
124
151
 
125
- - Pick a bold palette that reflects the **specific topic**. If the same palette would suit a completely different presentation, it's not specific enough.
126
- - Use **one dominant colour** (60–70% visual weight) + 1–2 supporting tones + one sharp accent.
127
- - Use dark backgrounds on title and conclusion slides, light on content slides ("sandwich" structure) — or commit fully to dark for a premium feel.
152
+ - Pick a bold palette for the **specific topic** not a generic one.
153
+ - One dominant colour (60–70%) + 1–2 supporting tones + one sharp accent.
154
+ - Dark backgrounds on title/conclusion slides, light on content ("sandwich") — or fully dark for premium feel.
128
155
 
129
- **Starter palettes:**
156
+ **Starter palettes** (use nearest named color for `setBackground`, hex helper for shapes):
130
157
 
131
- | Theme | Background | Accent | Text |
132
- |-------|-----------|--------|------|
133
- | Midnight | `navy` | `sky` | `white` |
134
- | Forest | `forest` | `sage` | `white` |
135
- | Coral | `coral` | `indigo` | `white` |
136
- | Terracotta | `terracotta` | `sand` | `white` |
137
- | Ocean | `cobalt` | `midnight` | `white` |
138
- | Minimal | `smoke` | `charcoal` | `black` |
158
+ | Theme | Background | Shape accent | Text |
159
+ |-------|-----------|-------------|------|
160
+ | Midnight | `'Black'` | `hex('#CADCFC')` | `'White'` |
161
+ | Forest | `'Green'` | `hex('#97BC62')` | `'White'` |
162
+ | Coral | `'Persimmon'` | `hex('#2F3C7E')` | `'White'` |
163
+ | Terracotta | `'Persimmon'` | `hex('#E7E8D1')` | `'White'` |
164
+ | Ocean | `'Blue'` | `hex('#21295C')` | `'White'` |
165
+ | Minimal | `'White'` | `hex('#36454F')` | `'Black'` |
139
166
 
140
167
  ### Layout
141
168
 
142
- - Every slide needs at least **one visual element** — shape, image, SVG icon, or table. Text-only slides are forgettable.
143
- - **Vary layouts** — never use the same structure slide after slide.
144
- - Pick one visual motif (e.g. rounded image frames, coloured icon circles, thick side accent bars) and carry it through every slide.
169
+ - Every slide needs at least **one visual element** — shape, image, SVG, or table.
170
+ - **Vary layouts** — never repeat the same structure slide after slide.
171
+ - Carry one visual motif through every slide (coloured accent bar, icon circles, etc.).
145
172
 
146
- **Layout options per slide:**
147
-
148
- - Two-column (text left, visual right)
149
- - Icon + text rows (icon in coloured circle, bold header, description)
150
- - 2×2 or 2×3 grid of cards
151
- - Large stat callout (big number + small label)
152
- - Half-background image with text overlay
153
- - Timeline / numbered steps
173
+ **Layout options:** two-column, icon+text rows, 2×2/2×3 grid, large stat callout, half-background image, timeline/steps.
154
174
 
155
175
  ### Typography
156
176
 
157
177
  - Left-align body text. Centre only titles.
158
- - **Font sizes:** titles use `Title` style (96pt); section headers `Header 1` (60pt); body `Body 1` or `Body 2`; captions `Body 3` or `Note`.
159
- - Minimum 64px margin from slide edges. 24–48px gap between content blocks.
178
+ - Minimum 64px margin from slide edges. 24–48px between content blocks.
160
179
 
161
- ### Things to never do
180
+ ### Never do
162
181
 
163
182
  - Repeat the same layout slide after slide
164
183
  - Centre body text
165
- - Use accent lines under slide titles (hallmark of AI-generated slides — use colour or whitespace instead)
166
- - Create text-only slides
167
- - Use low-contrast text — always check text against its background
168
- - Default to generic blue — pick colours that reflect the topic
184
+ - Use accent lines under slide titles (hallmark of AI-generated slides)
185
+ - Text-only slides
186
+ - Low-contrast text against background
169
187
 
170
188
  ---
171
189
 
172
190
  ## QA
173
191
 
174
- After generating or editing a deck:
175
-
176
- 1. **Self-check:** confirm all placeholder text has been replaced, no `lorem ipsum` or `[title here]` remains
177
- 2. **Tell the user** to upload the `.deck` to Figma Slides and review visually — this is the only way to catch rendering issues
178
- 3. **Offer to fix** any issues the user reports after upload
192
+ 1. Self-check: no placeholder text (`lorem ipsum`, `[title here]`) remains
193
+ 2. Tell the user to open the `.deck` in Figma Desktop to catch rendering issues
194
+ 3. Offer to fix anything they report
179
195
 
180
196
  ---
181
197
 
182
198
  ## Critical Format Rules
183
199
 
184
- - Blank text fields must use `" "` (space), **never** empty string — empty string crashes Figma
185
- - Image overrides require both a full-image hash and a ~320px thumbnail hash (40-char hex SHA-1)
186
- - Removed nodes use `phase: 'REMOVED'` never delete from `nodeChanges`
187
- - Chunk 1 of `canvas.fig` must be zstd-compressed — Figma silently rejects deflateRaw
200
+ - Blank text must be `" "` (space), never `""` — empty string crashes Figma
201
+ - Image overrides need both a full-image hash and thumbnail hash (40-char hex SHA-1)
202
+ - Removed nodes: set `phase: 'REMOVED'`, never delete from `nodeChanges`
203
+ - Chunk 1 of `canvas.fig` must be zstd-compressed
188
204
  - `thumbHash` must be `new Uint8Array(0)`, never `{}`