@nice2dev/icons 1.3.14 → 1.3.16

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.
Files changed (142) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/NiceDesktopIconExporter.js +688 -599
  3. package/dist/cjs/NiceFaviconGenerator.js +603 -417
  4. package/dist/cjs/NiceIconPicker.js +788 -508
  5. package/dist/cjs/NiceIconPreview.js +246 -188
  6. package/dist/cjs/NiceIconSetCreator.js +683 -552
  7. package/dist/cjs/NiceIconStacker.js +547 -171
  8. package/dist/cjs/NiceIconValue.js +27 -35
  9. package/dist/cjs/NtdIconBadge.js +384 -360
  10. package/dist/cjs/NtdIconMorph.js +419 -354
  11. package/dist/cjs/NtdStateMorph.js +150 -147
  12. package/dist/cjs/advancedIconSearch.js +373 -510
  13. package/dist/cjs/animationControls.js +518 -642
  14. package/dist/cjs/client.js +12 -15
  15. package/dist/cjs/createIcon.js +349 -251
  16. package/dist/cjs/design-tokens.js +324 -390
  17. package/dist/cjs/figmaExport.js +162 -257
  18. package/dist/cjs/figmaSync.js +234 -316
  19. package/dist/cjs/headless-ui.js +240 -368
  20. package/dist/cjs/iconAnalytics.js +337 -393
  21. package/dist/cjs/iconHtml.js +64 -86
  22. package/dist/cjs/iconMetadata.js +392 -472
  23. package/dist/cjs/iconParts.js +120 -90
  24. package/dist/cjs/iconStack.js +136 -155
  25. package/dist/cjs/iconStyles.js +1609 -504
  26. package/dist/cjs/iconValue.js +359 -430
  27. package/dist/cjs/icons/accessibility.js +1119 -134
  28. package/dist/cjs/icons/actions.js +1290 -330
  29. package/dist/cjs/icons/ai.js +1424 -144
  30. package/dist/cjs/icons/brand.js +1344 -172
  31. package/dist/cjs/icons/business.js +903 -193
  32. package/dist/cjs/icons/devtech.js +1656 -227
  33. package/dist/cjs/icons/ecommerce.js +802 -111
  34. package/dist/cjs/icons/education.js +1345 -199
  35. package/dist/cjs/icons/files.js +1597 -328
  36. package/dist/cjs/icons/fintech.js +793 -104
  37. package/dist/cjs/icons/food.js +1507 -153
  38. package/dist/cjs/icons/fun.js +786 -109
  39. package/dist/cjs/icons/gaming.js +916 -170
  40. package/dist/cjs/icons/health.js +623 -112
  41. package/dist/cjs/icons/index.js +34 -35
  42. package/dist/cjs/icons/input.js +282 -83
  43. package/dist/cjs/icons/legal.js +1065 -122
  44. package/dist/cjs/icons/media.js +1061 -267
  45. package/dist/cjs/icons/navigation.js +387 -122
  46. package/dist/cjs/icons/omniverk.js +747 -90
  47. package/dist/cjs/icons/realestate.js +1520 -193
  48. package/dist/cjs/icons/saas.js +867 -98
  49. package/dist/cjs/icons/science.js +1465 -165
  50. package/dist/cjs/icons/shapes.js +1316 -308
  51. package/dist/cjs/icons/smarthome.js +786 -90
  52. package/dist/cjs/icons/social.js +591 -59
  53. package/dist/cjs/icons/sports.js +1225 -133
  54. package/dist/cjs/icons/sustainability.js +1211 -139
  55. package/dist/cjs/icons/travel.js +1470 -148
  56. package/dist/cjs/icons/ui.js +1508 -315
  57. package/dist/cjs/icons/weather.js +1160 -173
  58. package/dist/cjs/index.js +566 -566
  59. package/dist/cjs/lottieIntegration.js +261 -266
  60. package/dist/cjs/nicetodev-icons.css +1 -1
  61. package/dist/cjs/particleEffects.js +270 -251
  62. package/dist/cjs/resolver.js +229 -284
  63. package/dist/cjs/rsc.js +175 -193
  64. package/dist/cjs/sharpen.js +73 -130
  65. package/dist/cjs/smilAnimations.js +371 -165
  66. package/dist/cjs/stacking.js +87 -122
  67. package/dist/cjs/tailwind-plugin.js +280 -320
  68. package/dist/cjs/types.js +46 -72
  69. package/dist/cjs/utilities.js +163 -324
  70. package/dist/cjs/variantProps.js +12 -52
  71. package/dist/esm/NiceDesktopIconExporter.js +671 -598
  72. package/dist/esm/NiceFaviconGenerator.js +583 -416
  73. package/dist/esm/NiceIconPicker.js +789 -507
  74. package/dist/esm/NiceIconPreview.js +247 -187
  75. package/dist/esm/NiceIconSetCreator.js +685 -551
  76. package/dist/esm/NiceIconStacker.js +549 -170
  77. package/dist/esm/NiceIconValue.js +29 -34
  78. package/dist/esm/NtdIconBadge.js +388 -359
  79. package/dist/esm/NtdIconMorph.js +423 -353
  80. package/dist/esm/NtdStateMorph.js +152 -146
  81. package/dist/esm/advancedIconSearch.js +391 -509
  82. package/dist/esm/animationControls.js +527 -641
  83. package/dist/esm/client.js +48 -10
  84. package/dist/esm/createIcon.js +350 -250
  85. package/dist/esm/design-tokens.js +334 -387
  86. package/dist/esm/figmaExport.js +170 -256
  87. package/dist/esm/figmaSync.js +237 -315
  88. package/dist/esm/headless-ui.js +254 -365
  89. package/dist/esm/iconAnalytics.js +342 -392
  90. package/dist/esm/iconHtml.js +67 -85
  91. package/dist/esm/iconMetadata.js +404 -471
  92. package/dist/esm/iconParts.js +125 -89
  93. package/dist/esm/iconStack.js +145 -154
  94. package/dist/esm/iconStyles.js +1620 -503
  95. package/dist/esm/iconValue.js +361 -429
  96. package/dist/esm/icons/accessibility.js +1133 -133
  97. package/dist/esm/icons/actions.js +1320 -329
  98. package/dist/esm/icons/ai.js +1441 -143
  99. package/dist/esm/icons/brand.js +1351 -171
  100. package/dist/esm/icons/business.js +931 -201
  101. package/dist/esm/icons/devtech.js +1687 -226
  102. package/dist/esm/icons/ecommerce.js +816 -110
  103. package/dist/esm/icons/education.js +1364 -198
  104. package/dist/esm/icons/files.js +1628 -327
  105. package/dist/esm/icons/fintech.js +807 -103
  106. package/dist/esm/icons/food.js +1524 -152
  107. package/dist/esm/icons/fun.js +801 -108
  108. package/dist/esm/icons/gaming.js +933 -169
  109. package/dist/esm/icons/health.js +636 -111
  110. package/dist/esm/icons/index.js +596 -32
  111. package/dist/esm/icons/input.js +326 -82
  112. package/dist/esm/icons/legal.js +1079 -121
  113. package/dist/esm/icons/media.js +1086 -266
  114. package/dist/esm/icons/navigation.js +401 -121
  115. package/dist/esm/icons/omniverk.js +759 -89
  116. package/dist/esm/icons/realestate.js +1544 -198
  117. package/dist/esm/icons/saas.js +880 -97
  118. package/dist/esm/icons/science.js +1482 -164
  119. package/dist/esm/icons/shapes.js +1343 -307
  120. package/dist/esm/icons/smarthome.js +799 -89
  121. package/dist/esm/icons/social.js +599 -58
  122. package/dist/esm/icons/sports.js +1240 -132
  123. package/dist/esm/icons/sustainability.js +1226 -138
  124. package/dist/esm/icons/travel.js +1486 -147
  125. package/dist/esm/icons/ui.js +1540 -314
  126. package/dist/esm/icons/weather.js +1181 -172
  127. package/dist/esm/index.js +756 -58
  128. package/dist/esm/lottieIntegration.js +264 -265
  129. package/dist/esm/nicetodev-icons.css +1 -1
  130. package/dist/esm/particleEffects.js +271 -250
  131. package/dist/esm/resolver.js +231 -283
  132. package/dist/esm/rsc.js +182 -192
  133. package/dist/esm/sharpen.js +78 -129
  134. package/dist/esm/smilAnimations.js +376 -164
  135. package/dist/esm/stacking.js +99 -121
  136. package/dist/esm/tailwind-plugin.js +282 -319
  137. package/dist/esm/types.js +50 -71
  138. package/dist/esm/utilities.js +177 -321
  139. package/dist/esm/variantProps.js +23 -52
  140. package/dist/types/icons/index.d.ts +1 -1
  141. package/dist/types/icons/science.d.ts +9 -0
  142. package/package.json +15 -22
@@ -1,342 +1,260 @@
1
- 'use strict';
2
-
3
- /**
4
- * @file figmaSync.ts
5
- * @description Bidirectional sync between Figma design files and the codebase.
6
- *
7
- * - Sync changes from Figma → codebase (import new/updated icons)
8
- * - Push code changes → Figma (export updated icons to Figma)
9
- * - Version tracking (track which version of icon is in Figma vs code)
10
- * - Conflict detection (detect when both sides changed)
11
- *
12
- * This module provides the data structures and logic for syncing.
13
- * The actual Figma API calls are delegated to callbacks so this
14
- * module can work with any Figma plugin or REST API implementation.
15
- *
16
- * @example
17
- * ```tsx
18
- * const manager = createFigmaSyncManager({
19
- * fetchFromFigma: async () => figmaIcons,
20
- * pushToFigma: async (icons) => { ... },
21
- * getLocalIcons: () => localIcons,
22
- * onConflict: (diff) => 'prefer-local',
23
- * });
24
- *
25
- * // Pull changes from Figma
26
- * const result = await manager.pull();
27
- *
28
- * // Push changes to Figma
29
- * const pushResult = await manager.push();
30
- *
31
- * // Full bidirectional sync
32
- * const syncResult = await manager.sync();
33
- * ```
34
- */
35
- /* ────────────────────────────────────────────────────────────────────────────
36
- HASH UTILITY
37
- ───────────────────────────────────────────────────────────────────────────── */
38
- /**
39
- * Simple content hash for change detection.
40
- * Uses a deterministic djb2-like hash for speed (no crypto needed).
41
- */
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
42
3
  function hashContent(content) {
43
- let hash = 5381;
44
- for (let i = 0; i < content.length; i++) {
45
- hash = ((hash << 5) + hash + content.charCodeAt(i)) & 0xffffffff;
46
- }
47
- return (hash >>> 0).toString(36);
4
+ let hash = 5381;
5
+ for (let i = 0; i < content.length; i++) {
6
+ hash = (hash << 5) + hash + content.charCodeAt(i) & 4294967295;
7
+ }
8
+ return (hash >>> 0).toString(36);
48
9
  }
49
- /** Generate a hash for an icon's content. */
50
10
  function hashIcon(icon) {
51
- var _a;
52
- return hashContent(icon.svgPaths.join('|') + icon.viewBox + ((_a = icon.variant) !== null && _a !== void 0 ? _a : ''));
11
+ return hashContent(icon.svgPaths.join("|") + icon.viewBox + (icon.variant ?? ""));
53
12
  }
54
- /* ────────────────────────────────────────────────────────────────────────────
55
- DIFF ENGINE
56
- ───────────────────────────────────────────────────────────────────────────── */
57
- /**
58
- * Computes a diff between two sets of tracked icons.
59
- *
60
- * @param localIcons - Icons in the codebase
61
- * @param figmaIcons - Icons in Figma
62
- * @param syncState - Previously synced hashes (for conflict detection)
63
- * @returns Array of diffs
64
- */
65
13
  function diffIconSets(localIcons, figmaIcons, syncState) {
66
- const diffs = [];
67
- const localMap = new Map(localIcons.map((i) => [i.name, i]));
68
- const figmaMap = new Map(figmaIcons.map((i) => [i.name, i]));
69
- const allNames = new Set([...localMap.keys(), ...figmaMap.keys()]);
70
- for (const name of allNames) {
71
- const local = localMap.get(name);
72
- const figma = figmaMap.get(name);
73
- const lastHash = syncState === null || syncState === void 0 ? void 0 : syncState.get(name);
74
- if (local && figma) {
75
- const localHash = hashIcon(local);
76
- const figmaHash = hashIcon(figma);
77
- if (localHash === figmaHash) {
78
- diffs.push({
79
- name,
80
- status: 'unchanged',
81
- direction: 'none',
82
- local,
83
- figma,
84
- lastSyncedHash: lastHash,
85
- });
86
- }
87
- else if (lastHash) {
88
- // Both sides changed since last sync
89
- const localChanged = localHash !== lastHash;
90
- const figmaChanged = figmaHash !== lastHash;
91
- if (localChanged && figmaChanged) {
92
- diffs.push({
93
- name,
94
- status: 'conflict',
95
- direction: 'both',
96
- local,
97
- figma,
98
- lastSyncedHash: lastHash,
99
- });
100
- }
101
- else if (localChanged) {
102
- diffs.push({
103
- name,
104
- status: 'modified',
105
- direction: 'code-to-figma',
106
- local,
107
- figma,
108
- lastSyncedHash: lastHash,
109
- });
110
- }
111
- else {
112
- diffs.push({
113
- name,
114
- status: 'modified',
115
- direction: 'figma-to-code',
116
- local,
117
- figma,
118
- lastSyncedHash: lastHash,
119
- });
120
- }
121
- }
122
- else {
123
- // No previous sync state — treat as conflict if different
124
- diffs.push({ name, status: 'conflict', direction: 'both', local, figma });
125
- }
126
- }
127
- else if (figma && !local) {
128
- diffs.push({ name, status: 'added', direction: 'figma-to-code', figma });
129
- }
130
- else if (local && !figma) {
131
- diffs.push({ name, status: 'added', direction: 'code-to-figma', local });
14
+ const diffs = [];
15
+ const localMap = new Map(localIcons.map((i) => [i.name, i]));
16
+ const figmaMap = new Map(figmaIcons.map((i) => [i.name, i]));
17
+ const allNames = /* @__PURE__ */ new Set([...localMap.keys(), ...figmaMap.keys()]);
18
+ for (const name of allNames) {
19
+ const local = localMap.get(name);
20
+ const figma = figmaMap.get(name);
21
+ const lastHash = syncState?.get(name);
22
+ if (local && figma) {
23
+ const localHash = hashIcon(local);
24
+ const figmaHash = hashIcon(figma);
25
+ if (localHash === figmaHash) {
26
+ diffs.push({
27
+ name,
28
+ status: "unchanged",
29
+ direction: "none",
30
+ local,
31
+ figma,
32
+ lastSyncedHash: lastHash
33
+ });
34
+ } else if (lastHash) {
35
+ const localChanged = localHash !== lastHash;
36
+ const figmaChanged = figmaHash !== lastHash;
37
+ if (localChanged && figmaChanged) {
38
+ diffs.push({
39
+ name,
40
+ status: "conflict",
41
+ direction: "both",
42
+ local,
43
+ figma,
44
+ lastSyncedHash: lastHash
45
+ });
46
+ } else if (localChanged) {
47
+ diffs.push({
48
+ name,
49
+ status: "modified",
50
+ direction: "code-to-figma",
51
+ local,
52
+ figma,
53
+ lastSyncedHash: lastHash
54
+ });
55
+ } else {
56
+ diffs.push({
57
+ name,
58
+ status: "modified",
59
+ direction: "figma-to-code",
60
+ local,
61
+ figma,
62
+ lastSyncedHash: lastHash
63
+ });
132
64
  }
65
+ } else {
66
+ diffs.push({ name, status: "conflict", direction: "both", local, figma });
67
+ }
68
+ } else if (figma && !local) {
69
+ diffs.push({ name, status: "added", direction: "figma-to-code", figma });
70
+ } else if (local && !figma) {
71
+ diffs.push({ name, status: "added", direction: "code-to-figma", local });
133
72
  }
134
- return diffs;
73
+ }
74
+ return diffs;
135
75
  }
136
- /* ────────────────────────────────────────────────────────────────────────────
137
- SYNC MANAGER
138
- ───────────────────────────────────────────────────────────────────────────── */
139
- const STORAGE_KEY = 'ntd-figma-sync-state';
140
- /**
141
- * Creates a FigmaSyncManager for bidirectional icon synchronization.
142
- */
76
+ const STORAGE_KEY = "ntd-figma-sync-state";
143
77
  function createFigmaSyncManager(config) {
144
- return new FigmaSyncManager(config);
78
+ return new FigmaSyncManager(config);
145
79
  }
146
80
  class FigmaSyncManager {
147
- constructor(config) {
148
- this.config = config;
149
- this.syncState = this.loadSyncState();
150
- }
151
- /** Pull changes from Figma → codebase. */
152
- async pull() {
153
- var _a, _b, _c;
154
- const start = performance.now();
155
- const figmaIcons = await this.config.fetchFromFigma();
156
- const localIcons = this.config.getLocalIcons();
157
- const diffs = diffIconSets(localIcons, figmaIcons, this.syncState);
158
- const pulled = [];
159
- const conflicts = [];
160
- const skipped = [];
161
- for (const diff of diffs) {
162
- if (diff.status === 'unchanged') {
163
- continue;
164
- }
165
- if (diff.status === 'conflict') {
166
- const resolution = (_c = (_b = (_a = this.config).onConflict) === null || _b === void 0 ? void 0 : _b.call(_a, diff)) !== null && _c !== void 0 ? _c : 'skip';
167
- if (resolution === 'prefer-figma') {
168
- pulled.push(diff);
169
- this.updateSyncHash(diff.name, diff.figma);
170
- }
171
- else if (resolution === 'skip') {
172
- skipped.push(diff);
173
- }
174
- else {
175
- // prefer-local — no pull needed
176
- skipped.push(diff);
177
- }
178
- conflicts.push(diff);
179
- }
180
- else if (diff.direction === 'figma-to-code') {
181
- pulled.push(diff);
182
- if (diff.figma) {
183
- this.updateSyncHash(diff.name, diff.figma);
184
- }
185
- }
81
+ constructor(config) {
82
+ this.config = config;
83
+ this.syncState = this.loadSyncState();
84
+ }
85
+ /** Pull changes from Figma → codebase. */
86
+ async pull() {
87
+ const start = performance.now();
88
+ const figmaIcons = await this.config.fetchFromFigma();
89
+ const localIcons = this.config.getLocalIcons();
90
+ const diffs = diffIconSets(localIcons, figmaIcons, this.syncState);
91
+ const pulled = [];
92
+ const conflicts = [];
93
+ const skipped = [];
94
+ for (const diff of diffs) {
95
+ if (diff.status === "unchanged") {
96
+ continue;
97
+ }
98
+ if (diff.status === "conflict") {
99
+ const resolution = this.config.onConflict?.(diff) ?? "skip";
100
+ if (resolution === "prefer-figma") {
101
+ pulled.push(diff);
102
+ this.updateSyncHash(diff.name, diff.figma);
103
+ } else if (resolution === "skip") {
104
+ skipped.push(diff);
105
+ } else {
106
+ skipped.push(diff);
186
107
  }
187
- this.saveSyncState();
188
- return {
189
- pulled,
190
- pushed: [],
191
- conflicts,
192
- skipped,
193
- duration: performance.now() - start,
194
- timestamp: Date.now(),
195
- };
196
- }
197
- /** Push changes from codebase → Figma. */
198
- async push() {
199
- var _a, _b, _c;
200
- const start = performance.now();
201
- const figmaIcons = await this.config.fetchFromFigma();
202
- const localIcons = this.config.getLocalIcons();
203
- const diffs = diffIconSets(localIcons, figmaIcons, this.syncState);
204
- const pushed = [];
205
- const conflicts = [];
206
- const skipped = [];
207
- const toPush = [];
208
- for (const diff of diffs) {
209
- if (diff.status === 'unchanged') {
210
- continue;
211
- }
212
- if (diff.status === 'conflict') {
213
- const resolution = (_c = (_b = (_a = this.config).onConflict) === null || _b === void 0 ? void 0 : _b.call(_a, diff)) !== null && _c !== void 0 ? _c : 'skip';
214
- if (resolution === 'prefer-local') {
215
- toPush.push(diff.local);
216
- pushed.push(diff);
217
- this.updateSyncHash(diff.name, diff.local);
218
- }
219
- else if (resolution === 'skip') {
220
- skipped.push(diff);
221
- }
222
- conflicts.push(diff);
223
- }
224
- else if (diff.direction === 'code-to-figma' && diff.local) {
225
- toPush.push(diff.local);
226
- pushed.push(diff);
227
- this.updateSyncHash(diff.name, diff.local);
228
- }
229
- }
230
- if (toPush.length > 0) {
231
- await this.config.pushToFigma(toPush);
108
+ conflicts.push(diff);
109
+ } else if (diff.direction === "figma-to-code") {
110
+ pulled.push(diff);
111
+ if (diff.figma) {
112
+ this.updateSyncHash(diff.name, diff.figma);
232
113
  }
233
- this.saveSyncState();
234
- return {
235
- pulled: [],
236
- pushed,
237
- conflicts,
238
- skipped,
239
- duration: performance.now() - start,
240
- timestamp: Date.now(),
241
- };
114
+ }
242
115
  }
243
- /** Full bidirectional sync. */
244
- async sync() {
245
- var _a, _b, _c;
246
- const start = performance.now();
247
- const figmaIcons = await this.config.fetchFromFigma();
248
- const localIcons = this.config.getLocalIcons();
249
- const diffs = diffIconSets(localIcons, figmaIcons, this.syncState);
250
- const pulled = [];
251
- const pushed = [];
252
- const conflicts = [];
253
- const skipped = [];
254
- const toPush = [];
255
- for (const diff of diffs) {
256
- if (diff.status === 'unchanged') {
257
- continue;
258
- }
259
- if (diff.status === 'conflict') {
260
- const resolution = (_c = (_b = (_a = this.config).onConflict) === null || _b === void 0 ? void 0 : _b.call(_a, diff)) !== null && _c !== void 0 ? _c : 'skip';
261
- conflicts.push(diff);
262
- if (resolution === 'prefer-local' && diff.local) {
263
- toPush.push(diff.local);
264
- pushed.push(diff);
265
- this.updateSyncHash(diff.name, diff.local);
266
- }
267
- else if (resolution === 'prefer-figma' && diff.figma) {
268
- pulled.push(diff);
269
- this.updateSyncHash(diff.name, diff.figma);
270
- }
271
- else {
272
- skipped.push(diff);
273
- }
274
- }
275
- else if (diff.direction === 'figma-to-code') {
276
- pulled.push(diff);
277
- if (diff.figma) {
278
- this.updateSyncHash(diff.name, diff.figma);
279
- }
280
- }
281
- else if (diff.direction === 'code-to-figma' && diff.local) {
282
- toPush.push(diff.local);
283
- pushed.push(diff);
284
- this.updateSyncHash(diff.name, diff.local);
285
- }
286
- }
287
- if (toPush.length > 0) {
288
- await this.config.pushToFigma(toPush);
116
+ this.saveSyncState();
117
+ return {
118
+ pulled,
119
+ pushed: [],
120
+ conflicts,
121
+ skipped,
122
+ duration: performance.now() - start,
123
+ timestamp: Date.now()
124
+ };
125
+ }
126
+ /** Push changes from codebase → Figma. */
127
+ async push() {
128
+ const start = performance.now();
129
+ const figmaIcons = await this.config.fetchFromFigma();
130
+ const localIcons = this.config.getLocalIcons();
131
+ const diffs = diffIconSets(localIcons, figmaIcons, this.syncState);
132
+ const pushed = [];
133
+ const conflicts = [];
134
+ const skipped = [];
135
+ const toPush = [];
136
+ for (const diff of diffs) {
137
+ if (diff.status === "unchanged") {
138
+ continue;
139
+ }
140
+ if (diff.status === "conflict") {
141
+ const resolution = this.config.onConflict?.(diff) ?? "skip";
142
+ if (resolution === "prefer-local") {
143
+ toPush.push(diff.local);
144
+ pushed.push(diff);
145
+ this.updateSyncHash(diff.name, diff.local);
146
+ } else if (resolution === "skip") {
147
+ skipped.push(diff);
289
148
  }
290
- this.saveSyncState();
291
- return {
292
- pulled,
293
- pushed,
294
- conflicts,
295
- skipped,
296
- duration: performance.now() - start,
297
- timestamp: Date.now(),
298
- };
149
+ conflicts.push(diff);
150
+ } else if (diff.direction === "code-to-figma" && diff.local) {
151
+ toPush.push(diff.local);
152
+ pushed.push(diff);
153
+ this.updateSyncHash(diff.name, diff.local);
154
+ }
299
155
  }
300
- /** Get current diff without making changes. */
301
- async diff() {
302
- const figmaIcons = await this.config.fetchFromFigma();
303
- const localIcons = this.config.getLocalIcons();
304
- return diffIconSets(localIcons, figmaIcons, this.syncState);
156
+ if (toPush.length > 0) {
157
+ await this.config.pushToFigma(toPush);
305
158
  }
306
- /** Get sync history from storage. */
307
- getSyncState() {
308
- return new Map(this.syncState);
159
+ this.saveSyncState();
160
+ return {
161
+ pulled: [],
162
+ pushed,
163
+ conflicts,
164
+ skipped,
165
+ duration: performance.now() - start,
166
+ timestamp: Date.now()
167
+ };
168
+ }
169
+ /** Full bidirectional sync. */
170
+ async sync() {
171
+ const start = performance.now();
172
+ const figmaIcons = await this.config.fetchFromFigma();
173
+ const localIcons = this.config.getLocalIcons();
174
+ const diffs = diffIconSets(localIcons, figmaIcons, this.syncState);
175
+ const pulled = [];
176
+ const pushed = [];
177
+ const conflicts = [];
178
+ const skipped = [];
179
+ const toPush = [];
180
+ for (const diff of diffs) {
181
+ if (diff.status === "unchanged") {
182
+ continue;
183
+ }
184
+ if (diff.status === "conflict") {
185
+ const resolution = this.config.onConflict?.(diff) ?? "skip";
186
+ conflicts.push(diff);
187
+ if (resolution === "prefer-local" && diff.local) {
188
+ toPush.push(diff.local);
189
+ pushed.push(diff);
190
+ this.updateSyncHash(diff.name, diff.local);
191
+ } else if (resolution === "prefer-figma" && diff.figma) {
192
+ pulled.push(diff);
193
+ this.updateSyncHash(diff.name, diff.figma);
194
+ } else {
195
+ skipped.push(diff);
196
+ }
197
+ } else if (diff.direction === "figma-to-code") {
198
+ pulled.push(diff);
199
+ if (diff.figma) {
200
+ this.updateSyncHash(diff.name, diff.figma);
201
+ }
202
+ } else if (diff.direction === "code-to-figma" && diff.local) {
203
+ toPush.push(diff.local);
204
+ pushed.push(diff);
205
+ this.updateSyncHash(diff.name, diff.local);
206
+ }
309
207
  }
310
- /** Reset sync state (forces full re-sync on next operation). */
311
- resetSyncState() {
312
- this.syncState.clear();
313
- this.saveSyncState();
208
+ if (toPush.length > 0) {
209
+ await this.config.pushToFigma(toPush);
314
210
  }
315
- // ── Private helpers ──
316
- updateSyncHash(name, icon) {
317
- this.syncState.set(name, hashIcon(icon));
211
+ this.saveSyncState();
212
+ return {
213
+ pulled,
214
+ pushed,
215
+ conflicts,
216
+ skipped,
217
+ duration: performance.now() - start,
218
+ timestamp: Date.now()
219
+ };
220
+ }
221
+ /** Get current diff without making changes. */
222
+ async diff() {
223
+ const figmaIcons = await this.config.fetchFromFigma();
224
+ const localIcons = this.config.getLocalIcons();
225
+ return diffIconSets(localIcons, figmaIcons, this.syncState);
226
+ }
227
+ /** Get sync history from storage. */
228
+ getSyncState() {
229
+ return new Map(this.syncState);
230
+ }
231
+ /** Reset sync state (forces full re-sync on next operation). */
232
+ resetSyncState() {
233
+ this.syncState.clear();
234
+ this.saveSyncState();
235
+ }
236
+ // ── Private helpers ──
237
+ updateSyncHash(name, icon) {
238
+ this.syncState.set(name, hashIcon(icon));
239
+ }
240
+ loadSyncState() {
241
+ const raw = this.config.storage?.get(STORAGE_KEY);
242
+ if (!raw) {
243
+ return /* @__PURE__ */ new Map();
318
244
  }
319
- loadSyncState() {
320
- var _a;
321
- const raw = (_a = this.config.storage) === null || _a === void 0 ? void 0 : _a.get(STORAGE_KEY);
322
- if (!raw) {
323
- return new Map();
324
- }
325
- try {
326
- return new Map(Object.entries(JSON.parse(raw)));
327
- }
328
- catch (_b) {
329
- return new Map();
330
- }
245
+ try {
246
+ return new Map(Object.entries(JSON.parse(raw)));
247
+ } catch {
248
+ return /* @__PURE__ */ new Map();
331
249
  }
332
- saveSyncState() {
333
- if (!this.config.storage) {
334
- return;
335
- }
336
- this.config.storage.set(STORAGE_KEY, JSON.stringify(Object.fromEntries(this.syncState)));
250
+ }
251
+ saveSyncState() {
252
+ if (!this.config.storage) {
253
+ return;
337
254
  }
255
+ this.config.storage.set(STORAGE_KEY, JSON.stringify(Object.fromEntries(this.syncState)));
256
+ }
338
257
  }
339
-
340
258
  exports.FigmaSyncManager = FigmaSyncManager;
341
259
  exports.createFigmaSyncManager = createFigmaSyncManager;
342
260
  exports.diffIconSets = diffIconSets;