gospelo-iconcraft-react 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,24 +1,24 @@
1
- # @gospelo-dev/iconcraft-react
1
+ # gospelo-iconcraft-react
2
2
 
3
3
  React components for creating emboss-style decorative icon shapes from SVG. Features 3D-looking shapes with highlights, shadows, and smooth animations.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @gospelo-dev/iconcraft-react
8
+ npm install gospelo-iconcraft-react
9
9
  ```
10
10
 
11
11
  ## Quick Start
12
12
 
13
13
  ```tsx
14
- import { IconCraft } from '@gospelo-dev/iconcraft-react';
14
+ import { IconCraftShape } from 'gospelo-iconcraft-react';
15
15
 
16
16
  function App() {
17
17
  return (
18
- <IconCraft
19
- svgContent="<svg>...</svg>"
18
+ <IconCraftShape
19
+ svg="<svg>...</svg>"
20
20
  mode="wax"
21
- baseColor="#6366f1"
21
+ shapeColor="#6366f1"
22
22
  />
23
23
  );
24
24
  }
@@ -31,12 +31,13 @@ function App() {
31
31
  Modern component with full feature support.
32
32
 
33
33
  ```tsx
34
- import { IconCraftShape } from '@gospelo-dev/iconcraft-react';
34
+ import { IconCraftShape } from 'gospelo-iconcraft-react';
35
35
 
36
36
  <IconCraftShape
37
37
  svg="<svg>...</svg>"
38
38
  mode="jelly"
39
- color="#10b981"
39
+ shapeColor="#10b981"
40
+ iconColor="#1d1d1f"
40
41
  size={120}
41
42
  animation="bounce"
42
43
  shadow
@@ -49,8 +50,9 @@ import { IconCraftShape } from '@gospelo-dev/iconcraft-react';
49
50
  |------|------|---------|-------------|
50
51
  | `svg` | `string` | required | SVG content string |
51
52
  | `mode` | `'jelly' \| 'droplet' \| 'wax'` | `'jelly'` | Shape mode |
52
- | `color` | `string` | `'#6366f1'` | Base color (hex) |
53
- | `iconStyle` | `'original' \| 'white' \| 'dark' \| 'emboss'` | `'emboss'` | Icon rendering style |
53
+ | `shapeColor` | `string` | `'#6366f1'` | Shape base color (hex) |
54
+ | `iconColor` | `string` | `'#1d1d1f'` | Icon color (for stroke/fill styles) |
55
+ | `iconStyle` | `'original' \| 'emboss' \| 'stroke' \| 'fill'` | `'emboss'` | Icon rendering style |
54
56
  | `size` | `number \| string` | - | Width and height |
55
57
  | `width` | `number \| string` | - | Width |
56
58
  | `height` | `number \| string` | - | Height |
@@ -72,7 +74,7 @@ import { IconCraftShape } from '@gospelo-dev/iconcraft-react';
72
74
  Original component for backwards compatibility.
73
75
 
74
76
  ```tsx
75
- import { IconCraft } from '@gospelo-dev/iconcraft-react';
77
+ import { IconCraft } from 'gospelo-iconcraft-react';
76
78
 
77
79
  <IconCraft
78
80
  svgContent="<svg>...</svg>"
@@ -151,7 +153,7 @@ interface AnimationOptions {
151
153
  ### Custom Animations
152
154
 
153
155
  ```tsx
154
- import { registerAnimation, IconCraftShape } from '@gospelo-dev/iconcraft-react';
156
+ import { registerAnimation, IconCraftShape } from 'gospelo-iconcraft-react';
155
157
 
156
158
  // Register custom animation
157
159
  registerAnimation('myAnimation', {
@@ -179,16 +181,16 @@ registerAnimation('myAnimation', {
179
181
  Low-level hook for direct WASM access.
180
182
 
181
183
  ```tsx
182
- import { useIconCraft } from '@gospelo-dev/iconcraft-react';
184
+ import { useIconCraft } from 'gospelo-iconcraft-react';
183
185
 
184
186
  function MyComponent() {
185
- const { result, loading, error, generate } = useIconCraft({
187
+ const { result, isLoading, error, generate } = useIconCraft({
186
188
  svg: svgContent,
187
189
  mode: 'wax',
188
- color: '#6366f1',
190
+ shapeColor: '#6366f1',
189
191
  });
190
192
 
191
- if (loading) return <div>Loading...</div>;
193
+ if (isLoading) return <div>Loading...</div>;
192
194
  if (error) return <div>Error: {error}</div>;
193
195
 
194
196
  return (
@@ -206,7 +208,7 @@ import {
206
208
  IconCraftProvider,
207
209
  useIconCraftStore,
208
210
  IconCraftView,
209
- } from '@gospelo-dev/iconcraft-react';
211
+ } from 'gospelo-iconcraft-react';
210
212
 
211
213
  function App() {
212
214
  return (
@@ -241,7 +243,7 @@ import type {
241
243
  AnimationOptions,
242
244
  IconCraftResult,
243
245
  IconCraftShapeProps,
244
- } from '@gospelo-dev/iconcraft-react';
246
+ } from 'gospelo-iconcraft-react';
245
247
  ```
246
248
 
247
249
  ## Browser Support
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
- import * as _gospelo_dev_iconcraft_wasm from '@gospelo-dev/iconcraft-wasm';
2
+ import * as gospelo_iconcraft_wasm from 'gospelo-iconcraft-wasm';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  type ShapeMode = 'jelly' | 'droplet' | 'wax';
6
- type IconStyle = 'original' | 'white' | 'dark' | 'emboss';
6
+ type IconStyle = 'original' | 'emboss' | 'stroke' | 'fill';
7
7
  /** Built-in animation types */
8
8
  type BuiltInAnimationType = 'none' | 'shake' | 'bounce' | 'pulse' | 'swing' | 'wobble' | 'jello' | 'heartbeat' | 'float' | 'spin' | 'rubberBand' | 'squish' | 'tada' | 'flip' | 'drop' | 'pop' | 'wiggle' | 'breathe';
9
9
  /**
@@ -95,7 +95,7 @@ interface IconCraftShapeProps {
95
95
  /** Shape mode: jelly, droplet, or wax */
96
96
  mode?: ShapeMode;
97
97
  /** Base color for the shape (hex) */
98
- color?: string;
98
+ shapeColor?: string;
99
99
  /** Custom color palette (overrides color) */
100
100
  palette?: Partial<ColorPalette>;
101
101
  /** Icon rendering style */
@@ -149,8 +149,9 @@ interface IconCraftProps {
149
149
  */
150
150
  interface IconCraftConfigOptions {
151
151
  mode?: ShapeMode;
152
- color?: string;
152
+ shapeColor?: string;
153
153
  iconStyle?: IconStyle;
154
+ iconColor?: string;
154
155
  shadow?: boolean;
155
156
  highlight?: boolean;
156
157
  offset?: number;
@@ -173,8 +174,9 @@ declare const DEFAULT_CONFIG: Required<Omit<IconCraftConfigOptions, 'width' | 'h
173
174
  */
174
175
  declare class IconCraftConfig {
175
176
  readonly mode: ShapeMode;
176
- readonly color: string;
177
+ readonly shapeColor: string;
177
178
  readonly iconStyle: IconStyle;
179
+ readonly iconColor: string;
178
180
  readonly shadow: boolean;
179
181
  readonly highlight: boolean;
180
182
  readonly offset: number;
@@ -199,7 +201,7 @@ declare class IconCraftConfig {
199
201
  resolution: number;
200
202
  simplify: number;
201
203
  includeIcon: boolean;
202
- color: string;
204
+ shapeColor: string;
203
205
  };
204
206
  /**
205
207
  * スタイル用のサイズを取得
@@ -325,7 +327,7 @@ interface WasmGenerateParams {
325
327
  resolution: number;
326
328
  simplify: number;
327
329
  includeIcon: boolean;
328
- color: string;
330
+ shapeColor: string;
329
331
  }
330
332
  /**
331
333
  * WASMマネージャー(Singleton)
@@ -342,7 +344,7 @@ declare class WasmManagerClass {
342
344
  /**
343
345
  * WASMモジュールを初期化
344
346
  */
345
- init(): Promise<typeof _gospelo_dev_iconcraft_wasm>;
347
+ init(): Promise<typeof gospelo_iconcraft_wasm>;
346
348
  /**
347
349
  * 初期化済みかどうか
348
350
  */
@@ -476,7 +478,7 @@ interface IconCraftViewProps {
476
478
  *
477
479
  * @example
478
480
  * ```tsx
479
- * const factory = new IconCraftFactory({ mode: 'wax', color: '#6366f1' });
481
+ * const factory = new IconCraftFactory({ mode: 'wax', shapeColor: '#6366f1' });
480
482
  * const icon = factory.create('<svg>...</svg>');
481
483
  *
482
484
  * <IconCraftView instance={icon} zIndex={10} />
@@ -484,6 +486,76 @@ interface IconCraftViewProps {
484
486
  */
485
487
  declare function IconCraftView({ instance, animation, animationTarget, animateOnHover, zIndex, className, style, onClick, onLoad, onError, }: IconCraftViewProps): react_jsx_runtime.JSX.Element | null;
486
488
 
489
+ /**
490
+ * IconCraftSimple Props
491
+ *
492
+ * シンプルなインターフェースでIconCraftを使用するためのコンポーネント
493
+ */
494
+ interface IconCraftSimpleProps {
495
+ /** SVG URL または SVG文字列 */
496
+ src: string;
497
+ /** シェイプモード */
498
+ mode?: ShapeMode;
499
+ /** アイコンスタイル */
500
+ iconStyle?: IconStyle;
501
+ /** アイコンの色(stroke/fillスタイル時) */
502
+ iconColor?: string;
503
+ /** シェイプカラー (hex) */
504
+ shapeColor?: string;
505
+ /** サイズ (px) */
506
+ size?: number;
507
+ /** アニメーション種類 */
508
+ animation?: AnimationType;
509
+ /** アニメーションオプション */
510
+ animationOptions?: AnimationOptions;
511
+ /** アニメーションターゲット */
512
+ animationTarget?: AnimationTarget;
513
+ /** ホバー時にアニメーション */
514
+ animateOnHover?: boolean;
515
+ /** Z-index */
516
+ zIndex?: number;
517
+ /** クラス名 */
518
+ className?: string;
519
+ /** インラインスタイル */
520
+ style?: React.CSSProperties;
521
+ /** クリックイベント */
522
+ onClick?: () => void;
523
+ /** ロード完了コールバック */
524
+ onLoad?: () => void;
525
+ /** エラーコールバック */
526
+ onError?: (error: string) => void;
527
+ /** 詳細設定(IconCraftViewに渡す追加props) */
528
+ viewProps?: Partial<Omit<IconCraftViewProps, 'instance'>>;
529
+ }
530
+ /**
531
+ * IconCraftSimple
532
+ *
533
+ * 最もシンプルな使い方でIconCraftを利用できるコンポーネント
534
+ *
535
+ * @example
536
+ * ```tsx
537
+ * // 基本的な使い方
538
+ * <IconCraftSimple src="/icon.svg" />
539
+ *
540
+ * // カスタマイズ
541
+ * <IconCraftSimple
542
+ * src="https://example.com/icon.svg"
543
+ * mode="jelly"
544
+ * shapeColor="#6366f1"
545
+ * size={200}
546
+ * animation="float"
547
+ * />
548
+ *
549
+ * // SVG文字列を直接渡す
550
+ * <IconCraftSimple
551
+ * src={`<svg>...</svg>`}
552
+ * mode="droplet"
553
+ * iconStyle="emboss"
554
+ * />
555
+ * ```
556
+ */
557
+ declare function IconCraftSimple({ src, mode, iconStyle, iconColor, shapeColor, size, animation, animationOptions, animationTarget, animateOnHover, zIndex, className, style, onClick, onLoad, onError, viewProps, }: IconCraftSimpleProps): react_jsx_runtime.JSX.Element;
558
+
487
559
  /**
488
560
  * IconCraftShape - Full-featured emboss icon component
489
561
  *
@@ -492,13 +564,13 @@ declare function IconCraftView({ instance, animation, animationTarget, animateOn
492
564
  * <IconCraftShape
493
565
  * svg="<svg>...</svg>"
494
566
  * mode="wax"
495
- * color="#6366f1"
567
+ * shapeColor="#6366f1"
496
568
  * size={120}
497
569
  * animation="float"
498
570
  * />
499
571
  * ```
500
572
  */
501
- declare function IconCraftShape({ svg, mode, color, iconStyle, shadow: _shadow, highlight: _highlight, offset, resolution, simplify, width, height, size, animation, animateOnHover, className, style, onLoad, onError, onClick, }: IconCraftShapeProps): react_jsx_runtime.JSX.Element | null;
573
+ declare function IconCraftShape({ svg, mode, shapeColor, iconStyle, shadow: _shadow, highlight: _highlight, offset, resolution, simplify, width, height, size, animation, animateOnHover, className, style, onLoad, onError, onClick, }: IconCraftShapeProps): react_jsx_runtime.JSX.Element | null;
502
574
 
503
575
  /**
504
576
  * Legacy IconCraft component
@@ -756,7 +828,7 @@ interface UseIconCraftCreateOptions {
756
828
  * @example
757
829
  * ```tsx
758
830
  * const createIcon = useIconCraftCreate({
759
- * config: { mode: 'wax', color: '#6366f1' },
831
+ * config: { mode: 'wax', shapeColor: '#6366f1' },
760
832
  * autoSelect: true,
761
833
  * });
762
834
  *
@@ -777,8 +849,8 @@ interface UseIconCraftOptions {
777
849
  svg: string;
778
850
  /** Shape mode */
779
851
  mode?: ShapeMode;
780
- /** Base color (hex) */
781
- color?: string;
852
+ /** Shape color (hex) */
853
+ shapeColor?: string;
782
854
  /** Icon style */
783
855
  iconStyle?: IconStyle;
784
856
  /** Contour offset */
@@ -812,7 +884,7 @@ interface UseIconCraftReturn {
812
884
  * const { result, isLoading, error } = useIconCraft({
813
885
  * svg: '<svg>...</svg>',
814
886
  * mode: 'wax',
815
- * color: '#6366f1',
887
+ * shapeColor: '#6366f1',
816
888
  * });
817
889
  * ```
818
890
  */
@@ -939,4 +1011,101 @@ declare function getKeyframes(type: AnimationType): string;
939
1011
  declare const keyframes: Record<BuiltInAnimationType, string>;
940
1012
  declare function injectKeyframes(type: AnimationType): void;
941
1013
 
942
- export { type AnimationOptions, type AnimationTarget, type AnimationType, type BuiltInAnimationType, type ColorPalette, type CustomAnimationDefinition, type CustomAnimationRegistry, DEFAULT_CONFIG, DEFAULT_METADATA, type EmbossIconData, type EmbossPath, IconCraft, IconCraftConfig, type IconCraftConfigOptions, type IconCraftContextValue, type IconCraftDispatcher, type IconCraftEvent, type IconCraftEventFilter, type IconCraftEventHandler, type IconCraftEventType, IconCraftFactory, IconCraftInstance, type IconCraftMetadata, type IconCraftProps, IconCraftProvider, type IconCraftProviderProps, IconCraftRegistry, type IconCraftResult, IconCraftShape, type IconCraftShapeProps, type IconCraftStoreActions, type IconCraftStoreState, IconCraftView, type IconCraftViewProps, type IconLayout, type IconStyle, type ShapeMode, type SvgPaths, type TransformOriginCustom, type TransformOriginPreset, type TransformOriginValue, type UseIconCraftCreateOptions, type UseIconCraftReturn$1 as UseIconCraftInstanceReturn, type UseIconCraftOptions, type UseIconCraftReturn, type UseIconCraftSelectionReturn, type WasmGenerateParams, WasmManager, animationDefaults, createDispatcher, defaultFactory, generateIconId, getAnimationDefaults, getAnimationName, getAnimationStyle, getCustomAnimation, getKeyframes, getTimestampFromId, getTransformOrigin, globalRegistry, injectKeyframes, keyframes, parseAnimationOptions, registerAnimation, useIconCraft, useIconCraftContext, useIconCraftCreate, useIconCraftEvent, useIconCraft$1 as useIconCraftInstance, useIconCraftSelection, useIconCraftStore, useLegacyIconCraft };
1014
+ /**
1015
+ * バックアップ用のアイコンデータ
1016
+ */
1017
+ interface IconBackupData {
1018
+ /** SVG URL または SVG文字列 */
1019
+ svg: string;
1020
+ /** シェイプモード */
1021
+ mode: ShapeMode;
1022
+ /** アイコンスタイル */
1023
+ iconStyle: IconStyle;
1024
+ /** シェイプカラー */
1025
+ shapeColor: string;
1026
+ /** サイズ */
1027
+ size: number;
1028
+ /** X座標(オプション) */
1029
+ x?: number;
1030
+ /** Y座標(オプション) */
1031
+ y?: number;
1032
+ /** Z-index(オプション) */
1033
+ zIndex?: number;
1034
+ /** アイコンの色(オプション) */
1035
+ iconColor?: string;
1036
+ /** アニメーション(オプション) */
1037
+ animation?: AnimationType;
1038
+ /** カスタムメタデータ(オプション) */
1039
+ metadata?: Record<string, unknown>;
1040
+ }
1041
+ /**
1042
+ * バックアップファイルの形式
1043
+ */
1044
+ interface IconCraftBackup {
1045
+ /** バージョン */
1046
+ version: string;
1047
+ /** 作成日時 */
1048
+ createdAt: string;
1049
+ /** ライセンス(オプション) */
1050
+ license?: string;
1051
+ /** ライセンス元URL(オプション) */
1052
+ licenseUrl?: string;
1053
+ /** アイコンデータの配列 */
1054
+ icons: IconBackupData[];
1055
+ /** グローバル設定(オプション) */
1056
+ settings?: {
1057
+ defaultMode?: ShapeMode;
1058
+ defaultIconStyle?: IconStyle;
1059
+ defaultShapeColor?: string;
1060
+ defaultSize?: number;
1061
+ };
1062
+ }
1063
+ /**
1064
+ * 現在のバックアップバージョン
1065
+ */
1066
+ declare const BACKUP_VERSION = "1.0.0";
1067
+ /**
1068
+ * バックアップ作成オプション
1069
+ */
1070
+ interface CreateBackupOptions {
1071
+ /** グローバル設定 */
1072
+ settings?: IconCraftBackup['settings'];
1073
+ /** ライセンス */
1074
+ license?: string;
1075
+ /** ライセンス元URL */
1076
+ licenseUrl?: string;
1077
+ }
1078
+ /**
1079
+ * バックアップデータを作成
1080
+ */
1081
+ declare function createBackup(icons: IconBackupData[], options?: CreateBackupOptions): IconCraftBackup;
1082
+ /**
1083
+ * バックアップをJSONファイルとしてダウンロード
1084
+ */
1085
+ declare function downloadBackup(backup: IconCraftBackup, filename?: string): void;
1086
+ /**
1087
+ * バックアップをエクスポート(JSON文字列として)
1088
+ */
1089
+ declare function exportBackup(backup: IconCraftBackup): string;
1090
+ /**
1091
+ * バックアップの検証結果
1092
+ */
1093
+ interface BackupValidationResult {
1094
+ valid: boolean;
1095
+ errors: string[];
1096
+ warnings: string[];
1097
+ }
1098
+ /**
1099
+ * バックアップデータを検証
1100
+ */
1101
+ declare function validateBackup(data: unknown): BackupValidationResult;
1102
+ /**
1103
+ * JSONファイルからバックアップを読み込み
1104
+ */
1105
+ declare function parseBackup(json: string): IconCraftBackup | null;
1106
+ /**
1107
+ * ファイル入力からバックアップを読み込み
1108
+ */
1109
+ declare function loadBackupFromFile(file: File): Promise<IconCraftBackup | null>;
1110
+
1111
+ export { type AnimationOptions, type AnimationTarget, type AnimationType, BACKUP_VERSION, type BackupValidationResult, type BuiltInAnimationType, type ColorPalette, type CreateBackupOptions, type CustomAnimationDefinition, type CustomAnimationRegistry, DEFAULT_CONFIG, DEFAULT_METADATA, type EmbossIconData, type EmbossPath, type IconBackupData, IconCraft, type IconCraftBackup, IconCraftConfig, type IconCraftConfigOptions, type IconCraftContextValue, type IconCraftDispatcher, type IconCraftEvent, type IconCraftEventFilter, type IconCraftEventHandler, type IconCraftEventType, IconCraftFactory, IconCraftInstance, type IconCraftMetadata, type IconCraftProps, IconCraftProvider, type IconCraftProviderProps, IconCraftRegistry, type IconCraftResult, IconCraftShape, type IconCraftShapeProps, IconCraftSimple, type IconCraftSimpleProps, type IconCraftStoreActions, type IconCraftStoreState, IconCraftView, type IconCraftViewProps, type IconLayout, type IconStyle, type ShapeMode, type SvgPaths, type TransformOriginCustom, type TransformOriginPreset, type TransformOriginValue, type UseIconCraftCreateOptions, type UseIconCraftReturn$1 as UseIconCraftInstanceReturn, type UseIconCraftOptions, type UseIconCraftReturn, type UseIconCraftSelectionReturn, type WasmGenerateParams, WasmManager, animationDefaults, createBackup, createDispatcher, defaultFactory, downloadBackup, exportBackup, generateIconId, getAnimationDefaults, getAnimationName, getAnimationStyle, getCustomAnimation, getKeyframes, getTimestampFromId, getTransformOrigin, globalRegistry, injectKeyframes, keyframes, loadBackupFromFile, parseAnimationOptions, parseBackup, registerAnimation, useIconCraft, useIconCraftContext, useIconCraftCreate, useIconCraftEvent, useIconCraft$1 as useIconCraftInstance, useIconCraftSelection, useIconCraftStore, useLegacyIconCraft, validateBackup };
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  // src/core/IconCraftConfig.ts
2
2
  var DEFAULT_CONFIG = {
3
3
  mode: "wax",
4
- color: "#6366f1",
4
+ shapeColor: "#6366f1",
5
5
  iconStyle: "emboss",
6
+ iconColor: "#1d1d1f",
6
7
  shadow: true,
7
8
  highlight: true,
8
9
  offset: 20,
@@ -17,8 +18,9 @@ var DEFAULT_CONFIG = {
17
18
  var IconCraftConfig = class _IconCraftConfig {
18
19
  constructor(options = {}) {
19
20
  this.mode = options.mode ?? DEFAULT_CONFIG.mode;
20
- this.color = options.color ?? DEFAULT_CONFIG.color;
21
+ this.shapeColor = options.shapeColor ?? DEFAULT_CONFIG.shapeColor;
21
22
  this.iconStyle = options.iconStyle ?? DEFAULT_CONFIG.iconStyle;
23
+ this.iconColor = options.iconColor ?? DEFAULT_CONFIG.iconColor;
22
24
  this.shadow = options.shadow ?? DEFAULT_CONFIG.shadow;
23
25
  this.highlight = options.highlight ?? DEFAULT_CONFIG.highlight;
24
26
  this.offset = options.offset ?? DEFAULT_CONFIG.offset;
@@ -36,8 +38,9 @@ var IconCraftConfig = class _IconCraftConfig {
36
38
  clone(overrides = {}) {
37
39
  return new _IconCraftConfig({
38
40
  mode: overrides.mode ?? this.mode,
39
- color: overrides.color ?? this.color,
41
+ shapeColor: overrides.shapeColor ?? this.shapeColor,
40
42
  iconStyle: overrides.iconStyle ?? this.iconStyle,
43
+ iconColor: overrides.iconColor ?? this.iconColor,
41
44
  shadow: overrides.shadow ?? this.shadow,
42
45
  highlight: overrides.highlight ?? this.highlight,
43
46
  offset: overrides.offset ?? this.offset,
@@ -61,7 +64,7 @@ var IconCraftConfig = class _IconCraftConfig {
61
64
  resolution: this.resolution,
62
65
  simplify: this.simplify,
63
66
  includeIcon: needsEmbossSvg,
64
- color: this.color
67
+ shapeColor: this.shapeColor
65
68
  };
66
69
  }
67
70
  /**
@@ -88,7 +91,7 @@ function createCacheKey(params) {
88
91
  resolution: params.resolution,
89
92
  simplify: params.simplify,
90
93
  includeIcon: params.includeIcon,
91
- color: params.color
94
+ shapeColor: params.shapeColor
92
95
  });
93
96
  }
94
97
  var shapeModeMap = {
@@ -110,7 +113,7 @@ var WasmManagerClass = class {
110
113
  if (this.module) return this.module;
111
114
  if (this.initPromise) return this.initPromise;
112
115
  this.initPromise = (async () => {
113
- const wasm = await import("./icon_craft_wasm-JDPURZOP.js");
116
+ const wasm = await import("gospelo-iconcraft-wasm");
114
117
  await wasm.default();
115
118
  this.module = wasm;
116
119
  return wasm;
@@ -140,7 +143,7 @@ var WasmManagerClass = class {
140
143
  params.resolution,
141
144
  params.simplify,
142
145
  params.includeIcon,
143
- params.color
146
+ params.shapeColor
144
147
  );
145
148
  if (result.success) {
146
149
  this.addToCache(cacheKey, result);
@@ -205,7 +208,7 @@ var IconCraftRegistry = class {
205
208
  register(instance) {
206
209
  const id = instance.id;
207
210
  const mode = instance.config.mode;
208
- const color = instance.config.color;
211
+ const color = instance.config.shapeColor;
209
212
  this.byId.set(id, instance);
210
213
  if (!this.byMode.has(mode)) {
211
214
  this.byMode.set(mode, /* @__PURE__ */ new Set());
@@ -223,7 +226,7 @@ var IconCraftRegistry = class {
223
226
  const instance = this.byId.get(id);
224
227
  if (!instance) return false;
225
228
  const mode = instance.config.mode;
226
- const color = instance.config.color;
229
+ const color = instance.config.shapeColor;
227
230
  this.byId.delete(id);
228
231
  this.byMode.get(mode)?.delete(id);
229
232
  if (this.byMode.get(mode)?.size === 0) {
@@ -417,7 +420,7 @@ var IconCraftInstance = class _IconCraftInstance {
417
420
  console.log("[IconCraftInstance] Generating with params:", {
418
421
  id: this._id,
419
422
  mode: params.mode,
420
- color: params.color
423
+ shapeColor: params.shapeColor
421
424
  });
422
425
  const result = await WasmManager.generate({
423
426
  svgContent,
@@ -426,7 +429,7 @@ var IconCraftInstance = class _IconCraftInstance {
426
429
  resolution: params.resolution,
427
430
  simplify: params.simplify,
428
431
  includeIcon: params.includeIcon,
429
- color: params.color
432
+ shapeColor: params.shapeColor
430
433
  });
431
434
  if (!result.success) {
432
435
  throw new Error(result.error || "Generation failed");
@@ -497,7 +500,7 @@ var IconCraftFactory = class _IconCraftFactory {
497
500
  const newConfig = this.prototype.clone(overrides);
498
501
  return new _IconCraftFactory({
499
502
  mode: newConfig.mode,
500
- color: newConfig.color,
503
+ shapeColor: newConfig.shapeColor,
501
504
  iconStyle: newConfig.iconStyle,
502
505
  shadow: newConfig.shadow,
503
506
  highlight: newConfig.highlight,
@@ -839,6 +842,7 @@ function IconCraftView({
839
842
  const renderedSvg = useMemo(() => {
840
843
  const instanceId = instance.id;
841
844
  const iconStyle = instance.config.iconStyle;
845
+ const iconColor = instance.config.iconColor;
842
846
  const result = instance.result;
843
847
  const mode = instance.config.mode;
844
848
  const isWax = mode === "wax";
@@ -861,27 +865,27 @@ function IconCraftView({
861
865
  const viewBoxMatch2 = svgContent2.match(/viewBox="([^"]*)"/);
862
866
  const viewBox2 = viewBoxMatch2 ? viewBoxMatch2[1] : "0 0 36 36";
863
867
  let innerSvg2 = svgContent2.replace(/<\/?svg[^>]*>/g, "");
864
- let iconFill2;
865
- let useOriginalColors2 = false;
868
+ let iconContent;
866
869
  switch (iconStyle) {
867
- case "white":
868
- iconFill2 = "#ffffff";
870
+ case "fill":
869
871
  innerSvg2 = innerSvg2.replace(/fill="[^"]*"/g, "");
872
+ iconContent = `<g fill="${iconColor}">${innerSvg2}</g>`;
870
873
  break;
871
- case "dark":
872
- iconFill2 = "#1d1d1f";
874
+ case "stroke":
873
875
  innerSvg2 = innerSvg2.replace(/fill="[^"]*"/g, "");
876
+ innerSvg2 = innerSvg2.replace(/stroke="[^"]*"/g, "");
877
+ innerSvg2 = innerSvg2.replace(/stroke-width="[^"]*"/g, "");
878
+ iconContent = `<g fill="none" stroke="${iconColor}" stroke-width="1.5">${innerSvg2}</g>`;
874
879
  break;
875
880
  case "original":
876
881
  default:
877
- iconFill2 = "currentColor";
878
- useOriginalColors2 = true;
882
+ iconContent = innerSvg2;
879
883
  break;
880
884
  }
881
885
  const layout2 = result?.icon_layout;
882
886
  const newIconSvg = `<g filter="none">
883
887
  <svg x="${layout2?.left_percent ?? 28}" y="${layout2?.top_percent ?? 28}" width="${layout2?.width_percent ?? 44}" height="${layout2?.height_percent ?? 44}" viewBox="${viewBox2}" overflow="visible">
884
- ${useOriginalColors2 ? innerSvg2 : `<g fill="${iconFill2}">${innerSvg2}</g>`}
888
+ ${iconContent}
885
889
  </svg>
886
890
  </g>`;
887
891
  svg2 = svg2.replace(/<g filter="none">[\s\S]*?<\/g>\s*<\/svg>$/, `${newIconSvg}
@@ -908,16 +912,18 @@ function IconCraftView({
908
912
  if (!result || !result.svg_paths?.clip) return "";
909
913
  const svgContent = instance.svgContent;
910
914
  if (!svgContent) return "";
911
- const color = instance.config.color;
915
+ const color = instance.config.shapeColor;
912
916
  const layout = result.icon_layout;
913
- let iconFill;
914
917
  let useOriginalColors = false;
918
+ let isStroke = false;
919
+ let iconFill;
915
920
  switch (iconStyle) {
916
- case "white":
917
- iconFill = "#ffffff";
921
+ case "fill":
922
+ iconFill = iconColor;
918
923
  break;
919
- case "dark":
920
- iconFill = "#1d1d1f";
924
+ case "stroke":
925
+ iconFill = "none";
926
+ isStroke = true;
921
927
  break;
922
928
  case "original":
923
929
  default:
@@ -933,9 +939,13 @@ function IconCraftView({
933
939
  const viewBoxMatch = svgContent.match(/viewBox="([^"]*)"/);
934
940
  const viewBox = viewBoxMatch ? viewBoxMatch[1] : "0 0 24 24";
935
941
  let innerSvg = svgContent.replace(/<\/?svg[^>]*>/g, "");
936
- if (iconStyle === "white" || iconStyle === "dark") {
942
+ if (iconStyle === "fill" || iconStyle === "stroke") {
937
943
  innerSvg = innerSvg.replace(/fill="[^"]*"/g, "");
938
944
  }
945
+ if (isStroke) {
946
+ innerSvg = innerSvg.replace(/stroke="[^"]*"/g, "");
947
+ innerSvg = innerSvg.replace(/stroke-width="[^"]*"/g, "");
948
+ }
939
949
  const bgGradient = isJellyOrDroplet ? `<linearGradient id="${gradientId}" x1="0%" y1="0%" x2="100%" y2="100%">
940
950
  <stop offset="0%" stop-color="${color}" stop-opacity="0.35"/>
941
951
  <stop offset="50%" stop-color="${color}" stop-opacity="0.4"/>
@@ -995,11 +1005,11 @@ function IconCraftView({
995
1005
  <svg x="${layout?.left_percent ?? 28}" y="${layout?.top_percent ?? 28}"
996
1006
  width="${layout?.width_percent ?? 44}" height="${layout?.height_percent ?? 44}"
997
1007
  viewBox="${viewBox}" overflow="visible">
998
- ${useOriginalColors ? innerSvg : `<g fill="${iconFill}">${innerSvg}</g>`}
1008
+ ${useOriginalColors ? innerSvg : isStroke ? `<g fill="none" stroke="${iconColor}" stroke-width="1.5">${innerSvg}</g>` : `<g fill="${iconFill}">${innerSvg}</g>`}
999
1009
  </svg>
1000
1010
  </svg>`;
1001
1011
  return svg;
1002
- }, [instance.id, instance.config.mode, instance.config.iconStyle, instance.config.color, instance.embossSvg, instance.result, instance.svgContent]);
1012
+ }, [instance.id, instance.config.mode, instance.config.iconStyle, instance.config.iconColor, instance.config.shapeColor, instance.embossSvg, instance.result, instance.svgContent]);
1003
1013
  const { width, height } = instance.config.getSize();
1004
1014
  const hoverAnim = animateOnHover ?? instance.config.animateOnHover;
1005
1015
  const shouldAnimate = hoverAnim ? isHovering : true;
@@ -1133,16 +1143,67 @@ function LoadingIndicator() {
1133
1143
  );
1134
1144
  }
1135
1145
 
1146
+ // src/components/IconCraftSimple.tsx
1147
+ import { useMemo as useMemo2 } from "react";
1148
+ import { jsx as jsx2 } from "react/jsx-runtime";
1149
+ function IconCraftSimple({
1150
+ src,
1151
+ mode = "jelly",
1152
+ iconStyle = "original",
1153
+ iconColor = "#1d1d1f",
1154
+ shapeColor = "#ffffff",
1155
+ size = 160,
1156
+ animation,
1157
+ animationOptions,
1158
+ animationTarget,
1159
+ animateOnHover,
1160
+ zIndex,
1161
+ className,
1162
+ style,
1163
+ onClick,
1164
+ onLoad,
1165
+ onError,
1166
+ viewProps
1167
+ }) {
1168
+ const instance = useMemo2(() => {
1169
+ const factory = new IconCraftFactory({
1170
+ mode,
1171
+ iconStyle,
1172
+ iconColor,
1173
+ shapeColor,
1174
+ size
1175
+ });
1176
+ return factory.create(src);
1177
+ }, [src, mode, iconStyle, iconColor, shapeColor, size]);
1178
+ const resolvedAnimation = animation && animationOptions ? { ...animationOptions, type: animation } : animation;
1179
+ return /* @__PURE__ */ jsx2(
1180
+ IconCraftView,
1181
+ {
1182
+ instance,
1183
+ animation: resolvedAnimation,
1184
+ animationTarget,
1185
+ animateOnHover,
1186
+ zIndex,
1187
+ className,
1188
+ style,
1189
+ onClick,
1190
+ onLoad,
1191
+ onError,
1192
+ ...viewProps
1193
+ }
1194
+ );
1195
+ }
1196
+
1136
1197
  // src/IconCraftShape.tsx
1137
- import { useEffect as useEffect2, useState as useState2, useMemo as useMemo2, useCallback } from "react";
1138
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1198
+ import { useEffect as useEffect2, useState as useState2, useMemo as useMemo3, useCallback } from "react";
1199
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1139
1200
  var wasmModule = null;
1140
1201
  var wasmInitPromise = null;
1141
1202
  async function initWasm() {
1142
1203
  if (wasmModule) return wasmModule;
1143
1204
  if (wasmInitPromise) return wasmInitPromise;
1144
1205
  wasmInitPromise = (async () => {
1145
- const wasm = await import("./icon_craft_wasm-JDPURZOP.js");
1206
+ const wasm = await import("gospelo-iconcraft-wasm");
1146
1207
  await wasm.default();
1147
1208
  wasmModule = wasm;
1148
1209
  return wasm;
@@ -1169,7 +1230,7 @@ function IconCraftShape({
1169
1230
  svg,
1170
1231
  // Shape Settings
1171
1232
  mode = "wax",
1172
- color = "#6366f1",
1233
+ shapeColor = "#6366f1",
1173
1234
  // Icon Style
1174
1235
  iconStyle = "emboss",
1175
1236
  // Effects (reserved for future use)
@@ -1198,7 +1259,7 @@ function IconCraftShape({
1198
1259
  const [isLoading, setIsLoading] = useState2(true);
1199
1260
  const [error, setError] = useState2(null);
1200
1261
  const [isHovering, setIsHovering] = useState2(false);
1201
- const animationOptions = useMemo2(
1262
+ const animationOptions = useMemo3(
1202
1263
  () => parseAnimationOptions(animation),
1203
1264
  [animation]
1204
1265
  );
@@ -1225,7 +1286,7 @@ function IconCraftShape({
1225
1286
  simplify,
1226
1287
  iconStyle === "emboss",
1227
1288
  // include_icon
1228
- color
1289
+ shapeColor
1229
1290
  );
1230
1291
  if (!wasmResult.success) {
1231
1292
  throw new Error(wasmResult.error || "Generation failed");
@@ -1239,7 +1300,7 @@ function IconCraftShape({
1239
1300
  } finally {
1240
1301
  setIsLoading(false);
1241
1302
  }
1242
- }, [svg, mode, color, iconStyle, offset, resolution, simplify, onLoad, onError]);
1303
+ }, [svg, mode, shapeColor, iconStyle, offset, resolution, simplify, onLoad, onError]);
1243
1304
  useEffect2(() => {
1244
1305
  generate();
1245
1306
  }, [generate]);
@@ -1259,7 +1320,7 @@ function IconCraftShape({
1259
1320
  const handleMouseEnter = animateOnHover ? () => setIsHovering(true) : void 0;
1260
1321
  const handleMouseLeave = animateOnHover ? () => setIsHovering(false) : void 0;
1261
1322
  if (isLoading) {
1262
- return /* @__PURE__ */ jsx2(
1323
+ return /* @__PURE__ */ jsx3(
1263
1324
  "div",
1264
1325
  {
1265
1326
  className,
@@ -1271,12 +1332,12 @@ function IconCraftShape({
1271
1332
  background: "#f0f0f0",
1272
1333
  borderRadius: "50%"
1273
1334
  },
1274
- children: /* @__PURE__ */ jsx2(LoadingSpinner, {})
1335
+ children: /* @__PURE__ */ jsx3(LoadingSpinner, {})
1275
1336
  }
1276
1337
  );
1277
1338
  }
1278
1339
  if (error) {
1279
- return /* @__PURE__ */ jsx2(
1340
+ return /* @__PURE__ */ jsx3(
1280
1341
  "div",
1281
1342
  {
1282
1343
  className,
@@ -1299,7 +1360,7 @@ function IconCraftShape({
1299
1360
  if (!result?.emboss_svg) {
1300
1361
  return null;
1301
1362
  }
1302
- return /* @__PURE__ */ jsx2(
1363
+ return /* @__PURE__ */ jsx3(
1303
1364
  "div",
1304
1365
  {
1305
1366
  className,
@@ -1322,8 +1383,8 @@ function LoadingSpinner() {
1322
1383
  animation: "spin 1s linear infinite"
1323
1384
  },
1324
1385
  children: [
1325
- /* @__PURE__ */ jsx2("style", { children: `@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }` }),
1326
- /* @__PURE__ */ jsx2(
1386
+ /* @__PURE__ */ jsx3("style", { children: `@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }` }),
1387
+ /* @__PURE__ */ jsx3(
1327
1388
  "circle",
1328
1389
  {
1329
1390
  cx: "12",
@@ -1349,7 +1410,7 @@ async function initWasm2() {
1349
1410
  if (wasmModule2) return wasmModule2;
1350
1411
  if (wasmInitPromise2) return wasmInitPromise2;
1351
1412
  wasmInitPromise2 = (async () => {
1352
- const wasm = await import("./icon_craft_wasm-JDPURZOP.js");
1413
+ const wasm = await import("gospelo-iconcraft-wasm");
1353
1414
  await wasm.default();
1354
1415
  wasmModule2 = wasm;
1355
1416
  return wasm;
@@ -1375,7 +1436,7 @@ function useIconCraft(options) {
1375
1436
  const {
1376
1437
  svg,
1377
1438
  mode = "wax",
1378
- color = "#6366f1",
1439
+ shapeColor = "#6366f1",
1379
1440
  iconStyle = "emboss",
1380
1441
  offset = 20,
1381
1442
  resolution = 256,
@@ -1413,7 +1474,7 @@ function useIconCraft(options) {
1413
1474
  resolution,
1414
1475
  simplify,
1415
1476
  iconStyle === "emboss",
1416
- color
1477
+ shapeColor
1417
1478
  );
1418
1479
  if (!wasmResult.success) {
1419
1480
  throw new Error(wasmResult.error || "Generation failed");
@@ -1424,7 +1485,7 @@ function useIconCraft(options) {
1424
1485
  } finally {
1425
1486
  setIsLoading(false);
1426
1487
  }
1427
- }, [svg, mode, color, iconStyle, offset, resolution, simplify]);
1488
+ }, [svg, mode, shapeColor, iconStyle, offset, resolution, simplify]);
1428
1489
  useEffect3(() => {
1429
1490
  if (autoGenerate && svg) {
1430
1491
  generate();
@@ -1451,7 +1512,7 @@ function useLegacyIconCraft(options) {
1451
1512
  const { result, isLoading, error, generate } = useIconCraft({
1452
1513
  svg: svgContent,
1453
1514
  mode,
1454
- color: baseColor,
1515
+ shapeColor: baseColor,
1455
1516
  offset,
1456
1517
  resolution,
1457
1518
  simplify: simplifyEpsilon,
@@ -1461,7 +1522,7 @@ function useLegacyIconCraft(options) {
1461
1522
  }
1462
1523
 
1463
1524
  // src/IconCraft.tsx
1464
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1525
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1465
1526
  function IconCraft({
1466
1527
  svgContent,
1467
1528
  mode = "jelly",
@@ -1477,13 +1538,13 @@ function IconCraft({
1477
1538
  const { result, isLoading, error } = useIconCraft({
1478
1539
  svg: svgContent,
1479
1540
  mode,
1480
- color: baseColor,
1541
+ shapeColor: baseColor,
1481
1542
  offset,
1482
1543
  resolution,
1483
1544
  simplify: simplifyEpsilon
1484
1545
  });
1485
1546
  if (isLoading) {
1486
- return /* @__PURE__ */ jsx3("div", { className, style, children: "Loading..." });
1547
+ return /* @__PURE__ */ jsx4("div", { className, style, children: "Loading..." });
1487
1548
  }
1488
1549
  if (error) {
1489
1550
  return /* @__PURE__ */ jsxs3("div", { className, style, children: [
@@ -1494,7 +1555,7 @@ function IconCraft({
1494
1555
  if (!result?.emboss_svg) {
1495
1556
  return null;
1496
1557
  }
1497
- return /* @__PURE__ */ jsx3(
1558
+ return /* @__PURE__ */ jsx4(
1498
1559
  "div",
1499
1560
  {
1500
1561
  className,
@@ -1514,7 +1575,7 @@ import {
1514
1575
  useContext,
1515
1576
  useReducer,
1516
1577
  useCallback as useCallback3,
1517
- useMemo as useMemo3,
1578
+ useMemo as useMemo4,
1518
1579
  useRef
1519
1580
  } from "react";
1520
1581
 
@@ -1559,7 +1620,7 @@ var DEFAULT_METADATA = {
1559
1620
  };
1560
1621
 
1561
1622
  // src/context/IconCraftProvider.tsx
1562
- import { jsx as jsx4 } from "react/jsx-runtime";
1623
+ import { jsx as jsx5 } from "react/jsx-runtime";
1563
1624
  var IconCraftContext = createContext(null);
1564
1625
  function reducer(state, action) {
1565
1626
  switch (action.type) {
@@ -1638,7 +1699,7 @@ function IconCraftProvider({
1638
1699
  }
1639
1700
  const dispatcher = dispatcherRef.current;
1640
1701
  const zIndexRef = useRef(0);
1641
- const factory = useMemo3(
1702
+ const factory = useMemo4(
1642
1703
  () => new IconCraftFactory(defaultConfig),
1643
1704
  [defaultConfig]
1644
1705
  );
@@ -1742,7 +1803,7 @@ function IconCraftProvider({
1742
1803
  }
1743
1804
  dispatch({ type: "CLEAR_ALL" });
1744
1805
  }, [state.instances, dispatcher]);
1745
- const contextValue = useMemo3(
1806
+ const contextValue = useMemo4(
1746
1807
  () => ({
1747
1808
  state,
1748
1809
  actions: {
@@ -1782,7 +1843,7 @@ function IconCraftProvider({
1782
1843
  defaultConfig
1783
1844
  ]
1784
1845
  );
1785
- return /* @__PURE__ */ jsx4(IconCraftContext.Provider, { value: contextValue, children });
1846
+ return /* @__PURE__ */ jsx5(IconCraftContext.Provider, { value: contextValue, children });
1786
1847
  }
1787
1848
  function useIconCraftContext() {
1788
1849
  const context = useContext(IconCraftContext);
@@ -1793,10 +1854,10 @@ function useIconCraftContext() {
1793
1854
  }
1794
1855
 
1795
1856
  // src/context/hooks.ts
1796
- import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo4 } from "react";
1857
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo5 } from "react";
1797
1858
  function useIconCraftStore() {
1798
1859
  const { actions, state } = useIconCraftContext();
1799
- return useMemo4(
1860
+ return useMemo5(
1800
1861
  () => ({
1801
1862
  // CRUD
1802
1863
  create: actions.create,
@@ -1836,7 +1897,7 @@ function useIconCraft2(id) {
1836
1897
  (zIndex) => actions.updateMetadata(id, { zIndex }),
1837
1898
  [actions, id]
1838
1899
  );
1839
- return useMemo4(
1900
+ return useMemo5(
1840
1901
  () => ({
1841
1902
  instance,
1842
1903
  metadata,
@@ -1866,7 +1927,7 @@ function useIconCraft2(id) {
1866
1927
  }
1867
1928
  function useIconCraftSelection() {
1868
1929
  const { actions, state } = useIconCraftContext();
1869
- const selected = useMemo4(
1930
+ const selected = useMemo5(
1870
1931
  () => Array.from(state.selection),
1871
1932
  [state.selection]
1872
1933
  );
@@ -1878,7 +1939,7 @@ function useIconCraftSelection() {
1878
1939
  const getSelectedInstances = useCallback4(() => {
1879
1940
  return selected.map((id) => state.instances.get(id)).filter((inst) => inst !== void 0);
1880
1941
  }, [selected, state.instances]);
1881
- return useMemo4(
1942
+ return useMemo5(
1882
1943
  () => ({
1883
1944
  selected,
1884
1945
  count: selected.length,
@@ -1915,7 +1976,100 @@ function useIconCraftCreate(options = {}) {
1915
1976
  [actions, config, metadata, autoSelect]
1916
1977
  );
1917
1978
  }
1979
+
1980
+ // src/utils/backup.ts
1981
+ var BACKUP_VERSION = "1.0.0";
1982
+ function createBackup(icons, options) {
1983
+ return {
1984
+ version: BACKUP_VERSION,
1985
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1986
+ license: options?.license,
1987
+ licenseUrl: options?.licenseUrl,
1988
+ icons,
1989
+ settings: options?.settings
1990
+ };
1991
+ }
1992
+ function downloadBackup(backup, filename) {
1993
+ const json = JSON.stringify(backup, null, 2);
1994
+ const blob = new Blob([json], { type: "application/json" });
1995
+ const url = URL.createObjectURL(blob);
1996
+ const a = document.createElement("a");
1997
+ a.href = url;
1998
+ a.download = filename || `iconcraft-backup-${Date.now()}.json`;
1999
+ document.body.appendChild(a);
2000
+ a.click();
2001
+ document.body.removeChild(a);
2002
+ URL.revokeObjectURL(url);
2003
+ }
2004
+ function exportBackup(backup) {
2005
+ return JSON.stringify(backup, null, 2);
2006
+ }
2007
+ function validateBackup(data) {
2008
+ const errors = [];
2009
+ const warnings = [];
2010
+ if (!data || typeof data !== "object") {
2011
+ return { valid: false, errors: ["Invalid backup format"], warnings: [] };
2012
+ }
2013
+ const backup = data;
2014
+ if (!backup.version) {
2015
+ errors.push("Missing version field");
2016
+ } else if (backup.version !== BACKUP_VERSION) {
2017
+ warnings.push(`Version mismatch: expected ${BACKUP_VERSION}, got ${backup.version}`);
2018
+ }
2019
+ if (!Array.isArray(backup.icons)) {
2020
+ errors.push("Missing or invalid icons array");
2021
+ } else {
2022
+ backup.icons.forEach((icon, index) => {
2023
+ if (!icon.svg) {
2024
+ errors.push(`Icon ${index}: missing svg field`);
2025
+ }
2026
+ if (!icon.mode) {
2027
+ warnings.push(`Icon ${index}: missing mode, will use default`);
2028
+ }
2029
+ if (!icon.shapeColor) {
2030
+ warnings.push(`Icon ${index}: missing shapeColor, will use default`);
2031
+ }
2032
+ });
2033
+ }
2034
+ return {
2035
+ valid: errors.length === 0,
2036
+ errors,
2037
+ warnings
2038
+ };
2039
+ }
2040
+ function parseBackup(json) {
2041
+ try {
2042
+ const data = JSON.parse(json);
2043
+ const validation = validateBackup(data);
2044
+ if (!validation.valid) {
2045
+ console.error("Backup validation failed:", validation.errors);
2046
+ return null;
2047
+ }
2048
+ if (validation.warnings.length > 0) {
2049
+ console.warn("Backup warnings:", validation.warnings);
2050
+ }
2051
+ return data;
2052
+ } catch (e) {
2053
+ console.error("Failed to parse backup:", e);
2054
+ return null;
2055
+ }
2056
+ }
2057
+ function loadBackupFromFile(file) {
2058
+ return new Promise((resolve) => {
2059
+ const reader = new FileReader();
2060
+ reader.onload = (e) => {
2061
+ const json = e.target?.result;
2062
+ resolve(parseBackup(json));
2063
+ };
2064
+ reader.onerror = () => {
2065
+ console.error("Failed to read file");
2066
+ resolve(null);
2067
+ };
2068
+ reader.readAsText(file);
2069
+ });
2070
+ }
1918
2071
  export {
2072
+ BACKUP_VERSION,
1919
2073
  DEFAULT_CONFIG,
1920
2074
  DEFAULT_METADATA,
1921
2075
  IconCraft,
@@ -1925,11 +2079,15 @@ export {
1925
2079
  IconCraftProvider,
1926
2080
  IconCraftRegistry,
1927
2081
  IconCraftShape,
2082
+ IconCraftSimple,
1928
2083
  IconCraftView,
1929
2084
  WasmManager,
1930
2085
  animationDefaults,
2086
+ createBackup,
1931
2087
  createDispatcher,
1932
2088
  defaultFactory,
2089
+ downloadBackup,
2090
+ exportBackup,
1933
2091
  generateIconId,
1934
2092
  getAnimationDefaults,
1935
2093
  getAnimationName,
@@ -1941,7 +2099,9 @@ export {
1941
2099
  globalRegistry,
1942
2100
  injectKeyframes,
1943
2101
  keyframes,
2102
+ loadBackupFromFile,
1944
2103
  parseAnimationOptions,
2104
+ parseBackup,
1945
2105
  registerAnimation,
1946
2106
  useIconCraft,
1947
2107
  useIconCraftContext,
@@ -1950,5 +2110,6 @@ export {
1950
2110
  useIconCraft2 as useIconCraftInstance,
1951
2111
  useIconCraftSelection,
1952
2112
  useIconCraftStore,
1953
- useLegacyIconCraft
2113
+ useLegacyIconCraft,
2114
+ validateBackup
1954
2115
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gospelo-iconcraft-react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "IconCraft React components - 3D decorative icon shapes from SVG",
5
5
  "license": "MIT",
6
6
  "author": "gorosun <goro-hayakawa@no-studio.net>",
@@ -32,7 +32,7 @@
32
32
  "react-dom": ">=18.0.0"
33
33
  },
34
34
  "dependencies": {
35
- "gospelo-iconcraft-wasm": "^0.1.0",
35
+ "gospelo-iconcraft-wasm": "^0.2.0",
36
36
  "ulid": "^3.0.2"
37
37
  },
38
38
  "devDependencies": {