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 +20 -18
- package/dist/index.d.ts +185 -16
- package/dist/index.js +224 -63
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
#
|
|
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
|
|
8
|
+
npm install gospelo-iconcraft-react
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
|
-
import {
|
|
14
|
+
import { IconCraftShape } from 'gospelo-iconcraft-react';
|
|
15
15
|
|
|
16
16
|
function App() {
|
|
17
17
|
return (
|
|
18
|
-
<
|
|
19
|
-
|
|
18
|
+
<IconCraftShape
|
|
19
|
+
svg="<svg>...</svg>"
|
|
20
20
|
mode="wax"
|
|
21
|
-
|
|
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 '
|
|
34
|
+
import { IconCraftShape } from 'gospelo-iconcraft-react';
|
|
35
35
|
|
|
36
36
|
<IconCraftShape
|
|
37
37
|
svg="<svg>...</svg>"
|
|
38
38
|
mode="jelly"
|
|
39
|
-
|
|
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
|
-
| `
|
|
53
|
-
| `
|
|
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 '
|
|
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 '
|
|
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 '
|
|
184
|
+
import { useIconCraft } from 'gospelo-iconcraft-react';
|
|
183
185
|
|
|
184
186
|
function MyComponent() {
|
|
185
|
-
const { result,
|
|
187
|
+
const { result, isLoading, error, generate } = useIconCraft({
|
|
186
188
|
svg: svgContent,
|
|
187
189
|
mode: 'wax',
|
|
188
|
-
|
|
190
|
+
shapeColor: '#6366f1',
|
|
189
191
|
});
|
|
190
192
|
|
|
191
|
-
if (
|
|
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 '
|
|
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 '
|
|
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
|
|
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' | '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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',
|
|
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
|
-
*
|
|
567
|
+
* shapeColor="#6366f1"
|
|
496
568
|
* size={120}
|
|
497
569
|
* animation="float"
|
|
498
570
|
* />
|
|
499
571
|
* ```
|
|
500
572
|
*/
|
|
501
|
-
declare function IconCraftShape({ svg, mode,
|
|
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',
|
|
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
|
-
/**
|
|
781
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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("
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
865
|
-
let useOriginalColors2 = false;
|
|
868
|
+
let iconContent;
|
|
866
869
|
switch (iconStyle) {
|
|
867
|
-
case "
|
|
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 "
|
|
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
|
-
|
|
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
|
-
${
|
|
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.
|
|
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 "
|
|
917
|
-
iconFill =
|
|
921
|
+
case "fill":
|
|
922
|
+
iconFill = iconColor;
|
|
918
923
|
break;
|
|
919
|
-
case "
|
|
920
|
-
iconFill = "
|
|
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 === "
|
|
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.
|
|
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
|
|
1138
|
-
import { jsx as
|
|
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("
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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__ */
|
|
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__ */
|
|
1335
|
+
children: /* @__PURE__ */ jsx3(LoadingSpinner, {})
|
|
1275
1336
|
}
|
|
1276
1337
|
);
|
|
1277
1338
|
}
|
|
1278
1339
|
if (error) {
|
|
1279
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1326
|
-
/* @__PURE__ */
|
|
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("
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1541
|
+
shapeColor: baseColor,
|
|
1481
1542
|
offset,
|
|
1482
1543
|
resolution,
|
|
1483
1544
|
simplify: simplifyEpsilon
|
|
1484
1545
|
});
|
|
1485
1546
|
if (isLoading) {
|
|
1486
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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.
|
|
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.
|
|
35
|
+
"gospelo-iconcraft-wasm": "^0.2.0",
|
|
36
36
|
"ulid": "^3.0.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|