@nice2dev/icons 1.1.10 → 1.2.1
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/CHANGELOG.md +173 -0
- package/dist/cjs/NiceDesktopIconExporter.js +2 -6
- package/dist/cjs/NiceFaviconGenerator.js +2 -1
- package/dist/cjs/NiceIconPicker.js +15 -20
- package/dist/cjs/NiceIconSetCreator.js +6 -29
- package/dist/cjs/NtdIconBadge.js +12 -12
- package/dist/cjs/NtdIconMorph.js +21 -11
- package/dist/cjs/NtdStateMorph.js +3 -3
- package/dist/cjs/animationControls.js +10 -3
- package/dist/cjs/createIcon.js +6 -10
- package/dist/cjs/headless-ui.js +3 -3
- package/dist/cjs/iconStyles.js +36 -34
- package/dist/cjs/icons/accessibility.js +13 -26
- package/dist/cjs/icons/actions.js +37 -50
- package/dist/cjs/icons/ai.js +15 -30
- package/dist/cjs/icons/brand.js +7 -18
- package/dist/cjs/icons/business.js +18 -106
- package/dist/cjs/icons/devtech.js +31 -142
- package/dist/cjs/icons/ecommerce.js +16 -32
- package/dist/cjs/icons/education.js +17 -34
- package/dist/cjs/icons/files.js +31 -62
- package/dist/cjs/icons/fintech.js +14 -28
- package/dist/cjs/icons/food.js +16 -32
- package/dist/cjs/icons/fun.js +13 -26
- package/dist/cjs/icons/gaming.js +15 -30
- package/dist/cjs/icons/health.js +13 -36
- package/dist/cjs/icons/index.js +4 -0
- package/dist/cjs/icons/legal.js +13 -26
- package/dist/cjs/icons/media.js +46 -46
- package/dist/cjs/icons/navigation.js +14 -28
- package/dist/cjs/icons/omniverk.js +10 -10
- package/dist/cjs/icons/realestate.js +17 -34
- package/dist/cjs/icons/saas.js +13 -26
- package/dist/cjs/icons/science.js +17 -34
- package/dist/cjs/icons/shapes.js +22 -44
- package/dist/cjs/icons/smarthome.js +13 -26
- package/dist/cjs/icons/social.js +8 -116
- package/dist/cjs/icons/sports.js +14 -28
- package/dist/cjs/icons/sustainability.js +15 -30
- package/dist/cjs/icons/travel.js +15 -30
- package/dist/cjs/icons/ui.js +39 -56
- package/dist/cjs/icons/weather.js +20 -40
- package/dist/cjs/index.js +4 -4
- package/dist/cjs/lottieIntegration.js +3 -3
- package/dist/cjs/nicetodev-icons.css +1 -1
- package/dist/cjs/particleEffects.js +11 -4
- package/dist/cjs/resolver.js +4 -0
- package/dist/cjs/rsc.js +1 -1
- package/dist/cjs/variantProps.js +2 -7
- package/dist/esm/NiceDesktopIconExporter.js +2 -6
- package/dist/esm/NiceFaviconGenerator.js +2 -1
- package/dist/esm/NiceIconPicker.js +16 -21
- package/dist/esm/NiceIconSetCreator.js +6 -29
- package/dist/esm/NtdIconBadge.js +12 -12
- package/dist/esm/NtdIconMorph.js +21 -11
- package/dist/esm/NtdStateMorph.js +3 -3
- package/dist/esm/animationControls.js +11 -4
- package/dist/esm/createIcon.js +7 -11
- package/dist/esm/headless-ui.js +3 -3
- package/dist/esm/iconStyles.js +36 -34
- package/dist/esm/icons/accessibility.js +13 -26
- package/dist/esm/icons/actions.js +37 -51
- package/dist/esm/icons/ai.js +15 -30
- package/dist/esm/icons/brand.js +7 -18
- package/dist/esm/icons/business.js +18 -106
- package/dist/esm/icons/devtech.js +31 -142
- package/dist/esm/icons/ecommerce.js +16 -32
- package/dist/esm/icons/education.js +17 -34
- package/dist/esm/icons/files.js +31 -62
- package/dist/esm/icons/fintech.js +14 -28
- package/dist/esm/icons/food.js +16 -32
- package/dist/esm/icons/fun.js +13 -26
- package/dist/esm/icons/gaming.js +15 -30
- package/dist/esm/icons/health.js +13 -36
- package/dist/esm/icons/index.js +3 -3
- package/dist/esm/icons/legal.js +13 -26
- package/dist/esm/icons/media.js +45 -47
- package/dist/esm/icons/navigation.js +14 -28
- package/dist/esm/icons/omniverk.js +10 -10
- package/dist/esm/icons/realestate.js +17 -34
- package/dist/esm/icons/saas.js +13 -26
- package/dist/esm/icons/science.js +17 -34
- package/dist/esm/icons/shapes.js +22 -44
- package/dist/esm/icons/smarthome.js +13 -26
- package/dist/esm/icons/social.js +8 -116
- package/dist/esm/icons/sports.js +14 -28
- package/dist/esm/icons/sustainability.js +15 -30
- package/dist/esm/icons/travel.js +15 -30
- package/dist/esm/icons/ui.js +39 -57
- package/dist/esm/icons/weather.js +20 -40
- package/dist/esm/index.js +4 -5
- package/dist/esm/lottieIntegration.js +3 -3
- package/dist/esm/nicetodev-icons.css +1 -1
- package/dist/esm/particleEffects.js +11 -4
- package/dist/esm/resolver.js +4 -0
- package/dist/esm/rsc.js +1 -1
- package/dist/esm/smilAnimations.js +1 -1
- package/dist/esm/variantProps.js +3 -7
- package/dist/types/NiceDesktopIconExporter.d.ts +1 -0
- package/dist/types/NtdIconBadge.d.ts +12 -4
- package/dist/types/NtdIconMorph.d.ts +10 -4
- package/dist/types/NtdStateMorph.d.ts +3 -1
- package/dist/types/createIcon.d.ts +1 -9
- package/dist/types/headless-ui.d.ts +6 -2
- package/dist/types/iconStyles.d.ts +33 -11
- package/dist/types/icons/actions.d.ts +1 -0
- package/dist/types/icons/index.d.ts +3 -3
- package/dist/types/icons/media.d.ts +3 -0
- package/dist/types/icons/ui.d.ts +2 -0
- package/dist/types/index.d.ts +2 -12
- package/dist/types/lottieIntegration.d.ts +3 -1
- package/dist/types/particleEffects.d.ts +3 -1
- package/dist/types/rsc.d.ts +1 -3
- package/dist/types/tailwind-plugin.d.ts +1 -1
- package/dist/types/types.d.ts +1 -2
- package/dist/types/variantProps.d.ts +3 -11
- package/package.json +1 -1
|
@@ -174,7 +174,8 @@ function drawParticle(ctx, p) {
|
|
|
174
174
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
175
175
|
COMPONENT
|
|
176
176
|
───────────────────────────────────────────────────────────────────────────── */
|
|
177
|
-
const NtdParticleIcon =
|
|
177
|
+
const NtdParticleIcon = /* @__PURE__ */ Object.assign(
|
|
178
|
+
/* @__PURE__ */ React.forwardRef(({ icon: Icon, particle, trigger = 'click', active, size = 'md', iconProps, className, style, onEffectEnd, }, ref) => {
|
|
178
179
|
var _a;
|
|
179
180
|
const containerRef = React.useRef(null);
|
|
180
181
|
const canvasRef = React.useRef(null);
|
|
@@ -263,7 +264,14 @@ const NtdParticleIcon = React.forwardRef(({ icon: Icon, particle, trigger = 'cli
|
|
|
263
264
|
height: resolvedSize,
|
|
264
265
|
cursor: trigger === 'click' || trigger === 'hover' ? 'pointer' : undefined,
|
|
265
266
|
...style,
|
|
266
|
-
}, onClick: trigger === 'click' ? emit : undefined,
|
|
267
|
+
}, onClick: trigger === 'click' ? emit : undefined, onKeyDown: trigger === 'click'
|
|
268
|
+
? (e) => {
|
|
269
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
270
|
+
e.preventDefault();
|
|
271
|
+
emit();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
: undefined, role: trigger === 'click' ? 'button' : undefined, tabIndex: trigger === 'click' ? 0 : undefined, onMouseEnter: trigger === 'hover' ? emit : undefined, children: [jsxRuntime.jsx(Icon, { size: size, ...iconProps }), jsxRuntime.jsx("canvas", { ref: canvasRef, width: canvasSize, height: canvasSize, style: {
|
|
267
275
|
position: 'absolute',
|
|
268
276
|
top: -canvasOffset,
|
|
269
277
|
left: -canvasOffset,
|
|
@@ -271,7 +279,6 @@ const NtdParticleIcon = React.forwardRef(({ icon: Icon, particle, trigger = 'cli
|
|
|
271
279
|
height: canvasSize,
|
|
272
280
|
pointerEvents: 'none',
|
|
273
281
|
} })] }));
|
|
274
|
-
});
|
|
275
|
-
NtdParticleIcon.displayName = 'NtdParticleIcon';
|
|
282
|
+
}), { displayName: 'NtdParticleIcon' });
|
|
276
283
|
|
|
277
284
|
exports.NtdParticleIcon = NtdParticleIcon;
|
package/dist/cjs/resolver.js
CHANGED
|
@@ -70,6 +70,7 @@ const NAME_MAP = {
|
|
|
70
70
|
'zoom-out': 'NtdZoomOut',
|
|
71
71
|
undo: 'NtdUndo',
|
|
72
72
|
redo: 'NtdRedo',
|
|
73
|
+
reply: 'NtdReply',
|
|
73
74
|
link: 'NtdLink',
|
|
74
75
|
login: 'NtdLogIn',
|
|
75
76
|
logout: 'NtdLogOut',
|
|
@@ -89,6 +90,7 @@ const NAME_MAP = {
|
|
|
89
90
|
image: 'NtdImage',
|
|
90
91
|
'link-2': 'NtdLink',
|
|
91
92
|
mail: 'NtdMail',
|
|
93
|
+
inbox: 'NtdInbox',
|
|
92
94
|
phone: 'NtdPhone',
|
|
93
95
|
user: 'NtdUser',
|
|
94
96
|
users: 'NtdUsers',
|
|
@@ -98,6 +100,7 @@ const NAME_MAP = {
|
|
|
98
100
|
bell: 'NtdBell',
|
|
99
101
|
grip: 'NtdGrid',
|
|
100
102
|
tag: 'NtdTag',
|
|
103
|
+
backspace: 'NtdBackspace',
|
|
101
104
|
bookmark: 'NtdBookmark',
|
|
102
105
|
flag: 'NtdFlag',
|
|
103
106
|
globe: 'NtdGlobe',
|
|
@@ -115,6 +118,7 @@ const NAME_MAP = {
|
|
|
115
118
|
camera: 'NtdCamera',
|
|
116
119
|
video: 'NtdVideo',
|
|
117
120
|
microphone: 'NtdMicrophone',
|
|
121
|
+
'microphone-off': 'NtdMicrophoneOff',
|
|
118
122
|
music: 'NtdMusic',
|
|
119
123
|
palette: 'NtdPalette',
|
|
120
124
|
// Misc
|
package/dist/cjs/rsc.js
CHANGED
|
@@ -49,7 +49,7 @@ function createIconRSC(options) {
|
|
|
49
49
|
}
|
|
50
50
|
// Resolve variant with fallback. `wireframe` always starts from `solid`
|
|
51
51
|
// (the full construction) — it is re-drawn mechanically, not authored.
|
|
52
|
-
const isCutout = variant === 'cutout'
|
|
52
|
+
const isCutout = variant === 'cutout';
|
|
53
53
|
const pathRenderer = isCutout || variant === 'wireframe' ? paths.solid : ((_a = paths[variant]) !== null && _a !== void 0 ? _a : paths.solid);
|
|
54
54
|
// Build render props
|
|
55
55
|
const renderProps = {
|
package/dist/cjs/variantProps.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @file variantProps.ts
|
|
5
5
|
* @description Discriminated unions and strict prop validation per icon variant.
|
|
6
6
|
*
|
|
7
|
-
* Provides narrowed prop types for each icon variant (solid, outline, duotone,
|
|
8
|
-
* sharp, rounded, mini, 3d) with variant-specific required/optional props.
|
|
7
|
+
* Provides narrowed prop types for each icon variant (solid, outline, duotone, cutout,
|
|
8
|
+
* sharp, rounded, mini, 3d, vivid) with variant-specific required/optional props.
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```tsx
|
|
@@ -42,10 +42,6 @@ function isDuotoneProps(props) {
|
|
|
42
42
|
function isCutoutProps(props) {
|
|
43
43
|
return props.variant === 'cutout';
|
|
44
44
|
}
|
|
45
|
-
/** @deprecated Use `isCutoutProps` instead. Narrows to `FlatIconProps` when `variant === 'flat'`. */
|
|
46
|
-
function isFlatProps(props) {
|
|
47
|
-
return props.variant === 'flat';
|
|
48
|
-
}
|
|
49
45
|
/** Narrows to `SharpIconProps` when `variant === 'sharp'`. */
|
|
50
46
|
function isSharpProps(props) {
|
|
51
47
|
return props.variant === 'sharp';
|
|
@@ -76,7 +72,6 @@ function toIconProps(props) {
|
|
|
76
72
|
|
|
77
73
|
exports.isCutoutProps = isCutoutProps;
|
|
78
74
|
exports.isDuotoneProps = isDuotoneProps;
|
|
79
|
-
exports.isFlatProps = isFlatProps;
|
|
80
75
|
exports.isMiniProps = isMiniProps;
|
|
81
76
|
exports.isOutlineProps = isOutlineProps;
|
|
82
77
|
exports.isRoundedProps = isRoundedProps;
|
|
@@ -630,14 +630,10 @@ const NiceDesktopIconExporter = ({ icon, initialConfig, onExport, className = ''
|
|
|
630
630
|
onExport === null || onExport === void 0 ? void 0 : onExport(icons);
|
|
631
631
|
};
|
|
632
632
|
const IconComponent = icon;
|
|
633
|
-
return (jsxs("div", { className: `nice-desktop-icon-exporter ${className}`, children: [jsxs("div", { className: "nice-desktop-icon-exporter__preview", children: [jsx("h3", { children: "Preview" }), jsx("div", { className: "nice-desktop-icon-exporter__preview-grid", children: [16, 32, 48, 64, 128, 256].map((size) => (jsxs("div", { className: "nice-desktop-icon-exporter__preview-item", children: [jsx("div", { style: {
|
|
633
|
+
return (jsxs("div", { className: `nice-desktop-icon-exporter ${className}`, children: [jsxs("div", { className: "nice-desktop-icon-exporter__preview", children: [jsx("h3", { children: "Preview" }), jsx("div", { className: "nice-desktop-icon-exporter__preview-grid", children: [16, 32, 48, 64, 128, 256].map((size) => (jsxs("div", { className: "nice-desktop-icon-exporter__preview-item", children: [jsx("div", { className: "nice-desktop-icon-exporter__preview-box", style: {
|
|
634
634
|
width: Math.min(size, 128),
|
|
635
635
|
height: Math.min(size, 128),
|
|
636
636
|
backgroundColor: config.backgroundColor || '#f0f0f0',
|
|
637
|
-
display: 'flex',
|
|
638
|
-
alignItems: 'center',
|
|
639
|
-
justifyContent: 'center',
|
|
640
|
-
borderRadius: 4,
|
|
641
637
|
}, children: jsx(IconComponent, { size: Math.min(size, 128) * (1 - config.padding * 2), fill: config.fillColor }) }), jsxs("span", { children: [size, "\u00D7", size] })] }, size))) })] }), jsxs("div", { className: "nice-desktop-icon-exporter__config", children: [jsx("h3", { children: "Configuration" }), jsxs("label", { children: ["Icon Name:", jsx("input", { type: "text", value: config.name, onChange: (e) => setConfig((c) => ({ ...c, name: e.target.value })) })] }), jsxs("label", { children: ["Fill Color:", jsx("input", { type: "color", value: config.fillColor, onChange: (e) => setConfig((c) => ({ ...c, fillColor: e.target.value })) })] }), jsxs("label", { children: ["Background:", jsx("input", { type: "color", value: config.backgroundColor || '#ffffff', onChange: (e) => setConfig((c) => ({ ...c, backgroundColor: e.target.value })) }), jsx("button", { onClick: () => setConfig((c) => ({ ...c, backgroundColor: undefined })), children: "Transparent" })] }), jsxs("label", { children: ["Padding: ", Math.round(config.padding * 100), "%", jsx("input", { type: "range", min: "0", max: "0.3", step: "0.01", value: config.padding, onChange: (e) => setConfig((c) => ({ ...c, padding: parseFloat(e.target.value) })) })] }), jsxs("div", { className: "nice-desktop-icon-exporter__platforms", children: [jsxs("label", { children: [jsx("input", { type: "checkbox", checked: config.includeWindows, onChange: (e) => setConfig((c) => ({ ...c, includeWindows: e.target.checked })) }), "Windows (.ico)"] }), jsxs("label", { children: [jsx("input", { type: "checkbox", checked: config.includeMacOS, onChange: (e) => setConfig((c) => ({ ...c, includeMacOS: e.target.checked })) }), "macOS (.iconset)"] }), jsxs("label", { children: [jsx("input", { type: "checkbox", checked: config.includeLinux, onChange: (e) => setConfig((c) => ({ ...c, includeLinux: e.target.checked })) }), "Linux (hicolor)"] }), jsxs("label", { children: [jsx("input", { type: "checkbox", checked: config.includeRetina, onChange: (e) => setConfig((c) => ({ ...c, includeRetina: e.target.checked })) }), "HiDPI/Retina (@2x, @3x)"] })] }), jsxs("div", { className: "nice-desktop-icon-exporter__sizes", children: [jsx("h4", { children: "Sizes:" }), DESKTOP_ICON_SIZES.map(({ size, label }) => (jsxs("label", { children: [jsx("input", { type: "checkbox", checked: config.sizes.includes(size), onChange: (e) => {
|
|
642
638
|
setConfig((c) => ({
|
|
643
639
|
...c,
|
|
@@ -645,7 +641,7 @@ const NiceDesktopIconExporter = ({ icon, initialConfig, onExport, className = ''
|
|
|
645
641
|
? [...c.sizes, size].sort((a, b) => a - b)
|
|
646
642
|
: c.sizes.filter((s) => s !== size),
|
|
647
643
|
}));
|
|
648
|
-
} }), label] }, size)))] })] }), jsxs("div", { className: "nice-desktop-icon-exporter__actions", children: [jsx("button", { onClick: handleExport, disabled: isExporting, children: isExporting ? `Exporting... ${Math.round(progress)}%` : 'Generate Icons' }), jsx("button", { onClick: downloadAll, disabled: isExporting || icons.length === 0, children: "Download All (ZIP)" })] }), icons.length > 0 && (jsxs("div", { className: "nice-desktop-icon-exporter__results", children: [jsxs("h3", { children: ["Generated Icons (", icons.length, ")"] }), jsx("div", { className: "nice-desktop-icon-exporter__results-grid", children: icons.map((exportedIcon) => (jsxs("div", { className: "nice-desktop-icon-exporter__result-item", children: [jsx("img", { src: exportedIcon.dataUrl, alt: exportedIcon.filename
|
|
644
|
+
} }), label] }, size)))] })] }), jsxs("div", { className: "nice-desktop-icon-exporter__actions", children: [jsx("button", { onClick: handleExport, disabled: isExporting, children: isExporting ? `Exporting... ${Math.round(progress)}%` : 'Generate Icons' }), jsx("button", { onClick: downloadAll, disabled: isExporting || icons.length === 0, children: "Download All (ZIP)" })] }), icons.length > 0 && (jsxs("div", { className: "nice-desktop-icon-exporter__results", children: [jsxs("h3", { children: ["Generated Icons (", icons.length, ")"] }), jsx("div", { className: "nice-desktop-icon-exporter__results-grid", children: icons.map((exportedIcon) => (jsxs("div", { className: "nice-desktop-icon-exporter__result-item", children: [jsx("img", { src: exportedIcon.dataUrl, alt: exportedIcon.filename }), jsx("span", { children: exportedIcon.filename }), jsx("button", { onClick: () => downloadSingle(exportedIcon), children: "Download" })] }, exportedIcon.filename))) })] }))] }));
|
|
649
645
|
};
|
|
650
646
|
|
|
651
647
|
export { DESKTOP_ICON_SIZES, LINUX_HICOLOR_DIRS, NiceDesktopIconExporter, RETINA_VARIANTS, useDesktopIconExporter };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useCallback } from 'react';
|
|
3
|
+
import { NtdDownload } from './icons/actions.js';
|
|
3
4
|
|
|
4
5
|
/* ══════════════════════════════════════════════════════════════════════════════
|
|
5
6
|
Constants
|
|
@@ -233,7 +234,7 @@ function NiceFaviconGenerator({ icon, fill = '#1e1e1e', manifestConfig, onGenera
|
|
|
233
234
|
return (jsxs("div", { className: `nice-favicon-generator ${className}`, style: styles.container, children: [jsxs("div", { style: styles.section, children: [jsx("h3", { style: styles.sectionTitle, children: "Manifest Configuration" }), jsxs("div", { style: styles.formGrid, children: [jsxs("div", { style: styles.formGroup, children: [jsx("label", { style: styles.label, children: "App Name" }), jsx("input", { type: "text", value: config.name, onChange: (e) => setConfig((c) => ({ ...c, name: e.target.value })), style: styles.input })] }), jsxs("div", { style: styles.formGroup, children: [jsx("label", { style: styles.label, children: "Short Name" }), jsx("input", { type: "text", value: config.shortName, onChange: (e) => setConfig((c) => ({ ...c, shortName: e.target.value })), style: styles.input })] }), jsxs("div", { style: styles.formGroup, children: [jsx("label", { style: styles.label, children: "Theme Color" }), jsx("input", { type: "color", value: config.themeColor, onChange: (e) => setConfig((c) => ({ ...c, themeColor: e.target.value })), style: styles.colorInput })] }), jsxs("div", { style: styles.formGroup, children: [jsx("label", { style: styles.label, children: "Background Color" }), jsx("input", { type: "color", value: config.backgroundColor, onChange: (e) => setConfig((c) => ({ ...c, backgroundColor: e.target.value })), style: styles.colorInput })] }), jsxs("div", { style: styles.formGroup, children: [jsx("label", { style: styles.label, children: "Display Mode" }), jsxs("select", { value: config.display, onChange: (e) => setConfig((c) => ({ ...c, display: e.target.value })), style: styles.input, children: [jsx("option", { value: "standalone", children: "Standalone" }), jsx("option", { value: "fullscreen", children: "Fullscreen" }), jsx("option", { value: "minimal-ui", children: "Minimal UI" }), jsx("option", { value: "browser", children: "Browser" })] })] }), jsxs("div", { style: styles.formGroup, children: [jsx("label", { style: styles.label, children: "Start URL" }), jsx("input", { type: "text", value: config.startUrl, onChange: (e) => setConfig((c) => ({ ...c, startUrl: e.target.value })), style: styles.input })] })] })] }), jsxs("div", { style: styles.actions, children: [jsx("button", { onClick: handleGenerate, disabled: isGenerating, style: {
|
|
234
235
|
...styles.button,
|
|
235
236
|
...(isGenerating ? styles.buttonDisabled : styles.buttonPrimary),
|
|
236
|
-
}, children: isGenerating ? 'Generating...' : 'Generate Favicons' }), assets.length > 0 && (jsx("button", { onClick: downloadAll, style: { ...styles.button, ...styles.buttonSecondary }, children: "Download All" }))] }), assets.length > 0 && (jsxs("div", { style: styles.section, children: [jsxs("div", { style: styles.tabs, children: [jsx("button", { style: { ...styles.tab, ...(activeTab === 'preview' ? styles.tabActive : {}) }, onClick: () => setActiveTab('preview'), children: "Preview" }), jsx("button", { style: { ...styles.tab, ...(activeTab === 'manifest' ? styles.tabActive : {}) }, onClick: () => setActiveTab('manifest'), children: "manifest.json" }), jsx("button", { style: { ...styles.tab, ...(activeTab === 'html' ? styles.tabActive : {}) }, onClick: () => setActiveTab('html'), children: "HTML Tags" })] }), activeTab === 'preview' && (jsx("div", { style: styles.assetGrid, children: assets.map((asset) => (jsxs("div", { style: styles.assetCard, children: [jsx("div", { style: styles.assetPreview, children: jsx("img", { src: asset.dataUrl, alt: asset.filename, style: { maxWidth: '64px', maxHeight: '64px' } }) }), jsxs("div", { style: styles.assetInfo, children: [jsx("span", { style: styles.assetName, children: asset.filename }), jsxs("span", { style: styles.assetSize, children: [asset.size, "x", asset.size] }), jsx("span", { style: styles.assetPurpose, children: asset.purpose })] }), jsx("button", { onClick: () => downloadSingle(asset), style: styles.downloadBtn, children: "
|
|
237
|
+
}, children: isGenerating ? 'Generating...' : 'Generate Favicons' }), assets.length > 0 && (jsx("button", { onClick: downloadAll, style: { ...styles.button, ...styles.buttonSecondary }, children: "Download All" }))] }), assets.length > 0 && (jsxs("div", { style: styles.section, children: [jsxs("div", { style: styles.tabs, children: [jsx("button", { style: { ...styles.tab, ...(activeTab === 'preview' ? styles.tabActive : {}) }, onClick: () => setActiveTab('preview'), children: "Preview" }), jsx("button", { style: { ...styles.tab, ...(activeTab === 'manifest' ? styles.tabActive : {}) }, onClick: () => setActiveTab('manifest'), children: "manifest.json" }), jsx("button", { style: { ...styles.tab, ...(activeTab === 'html' ? styles.tabActive : {}) }, onClick: () => setActiveTab('html'), children: "HTML Tags" })] }), activeTab === 'preview' && (jsx("div", { style: styles.assetGrid, children: assets.map((asset) => (jsxs("div", { style: styles.assetCard, children: [jsx("div", { style: styles.assetPreview, children: jsx("img", { src: asset.dataUrl, alt: asset.filename, style: { maxWidth: '64px', maxHeight: '64px' } }) }), jsxs("div", { style: styles.assetInfo, children: [jsx("span", { style: styles.assetName, children: asset.filename }), jsxs("span", { style: styles.assetSize, children: [asset.size, "x", asset.size] }), jsx("span", { style: styles.assetPurpose, children: asset.purpose })] }), jsx("button", { onClick: () => downloadSingle(asset), style: styles.downloadBtn, "aria-label": `Download ${asset.filename}`, children: jsx(NtdDownload, { size: 14, variant: "outline" }) })] }, asset.filename))) })), activeTab === 'manifest' && jsx("pre", { style: styles.codeBlock, children: getManifestJson() }), activeTab === 'html' && jsx("pre", { style: styles.codeBlock, children: getHtmlTags() })] })), jsxs("div", { style: styles.reference, children: [jsx("h4", { style: styles.referenceTitle, children: "Favicon Sizes Reference" }), jsxs("table", { style: styles.table, children: [jsx("thead", { children: jsxs("tr", { children: [jsx("th", { style: styles.th, children: "File" }), jsx("th", { style: styles.th, children: "Size" }), jsx("th", { style: styles.th, children: "Purpose" })] }) }), jsx("tbody", { children: FAVICON_SIZES.map((f) => (jsxs("tr", { children: [jsxs("td", { style: styles.td, children: [f.name, ".", f.format] }), jsxs("td", { style: styles.td, children: [f.size, "x", f.size] }), jsx("td", { style: styles.td, children: f.purpose })] }, f.name))) })] })] })] }));
|
|
237
238
|
}
|
|
238
239
|
/* ══════════════════════════════════════════════════════════════════════════════
|
|
239
240
|
Styles
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { forwardRef, useState, useRef, useCallback, useImperativeHandle,
|
|
2
|
+
import { forwardRef, useState, useRef, useMemo, useCallback, useImperativeHandle, useEffect } from 'react';
|
|
3
|
+
import { NtdSearch, NtdCheck } from './icons/actions.js';
|
|
4
|
+
import { NtdGrid } from './icons/files.js';
|
|
5
|
+
import { NtdInbox } from './icons/media.js';
|
|
6
|
+
import { NtdChevronDown } from './icons/navigation.js';
|
|
7
|
+
import { NtdStar, NtdClock } from './icons/ui.js';
|
|
3
8
|
|
|
4
9
|
const MAX_HISTORY_ITEMS = 20;
|
|
5
|
-
/* ───
|
|
6
|
-
const Chevron = () =>
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
/* ─── Clock SVG (history) ─── */
|
|
12
|
-
const ClockIcon = () => (jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("circle", { cx: "12", cy: "12", r: "10" }), jsx("polyline", { points: "12 6 12 12 16 14" })] }));
|
|
13
|
-
/* ─── Check SVG (multi-select) ─── */
|
|
14
|
-
const CheckIcon = () => (jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
10
|
+
/* ─── Small icons: the package's own (until 1.2.0 these were pasted SVGs) ─── */
|
|
11
|
+
const Chevron = () => jsx(NtdChevronDown, { size: 12, variant: "outline" });
|
|
12
|
+
const SearchIcon = () => jsx(NtdSearch, { size: 14, variant: "outline" });
|
|
13
|
+
const StarIcon = ({ filled }) => (jsx(NtdStar, { size: 12, variant: filled ? 'solid' : 'outline' }));
|
|
14
|
+
const ClockIcon = () => jsx(NtdClock, { size: 12, variant: "outline" });
|
|
15
|
+
const CheckIcon = () => jsx(NtdCheck, { size: 10, variant: "outline" });
|
|
15
16
|
/* ─── localStorage helpers ─── */
|
|
16
17
|
function loadFromStorage(key, fallback) {
|
|
17
18
|
if (typeof window === 'undefined') {
|
|
@@ -68,7 +69,7 @@ function saveToStorage(key, value) {
|
|
|
68
69
|
* }
|
|
69
70
|
* ```
|
|
70
71
|
*/
|
|
71
|
-
const NiceIconPicker = forwardRef(function NiceIconPicker({ icons, value = null, values = [], onChange, onChangeMulti, multiSelect = false, maxSelections, placeholder = 'Select icon…', variant = 'solid', gridIconSize = 'md', triggerIconSize = 'sm', categories: categoriesProp, className, disabled = false, clearable = true, virtualized = false, virtualizedItemCount = 100, showHistory = false, showFavorites = false, storageKeyPrefix = 'ntd-icon-picker', enableDragAndDrop = false, onDragStart, onDragEnd, }, ref) {
|
|
72
|
+
const NiceIconPicker = /* @__PURE__ */ forwardRef(function NiceIconPicker({ icons, value = null, values = [], onChange, onChangeMulti, multiSelect = false, maxSelections, placeholder = 'Select icon…', variant = 'solid', gridIconSize = 'md', triggerIconSize = 'sm', categories: categoriesProp, className, disabled = false, clearable = true, virtualized = false, virtualizedItemCount = 100, showHistory = false, showFavorites = false, storageKeyPrefix = 'ntd-icon-picker', enableDragAndDrop = false, onDragStart, onDragEnd, }, ref) {
|
|
72
73
|
var _a;
|
|
73
74
|
const [isOpen, setIsOpen] = useState(false);
|
|
74
75
|
const [search, setSearch] = useState('');
|
|
@@ -83,13 +84,7 @@ const NiceIconPicker = forwardRef(function NiceIconPicker({ icons, value = null,
|
|
|
83
84
|
const [history, setHistory] = useState(() => loadFromStorage(historyKey, []));
|
|
84
85
|
// Multi-select state (internal when uncontrolled)
|
|
85
86
|
const [internalValues, setInternalValues] = useState([]);
|
|
86
|
-
const selectedValues = multiSelect
|
|
87
|
-
? values.length > 0
|
|
88
|
-
? values
|
|
89
|
-
: internalValues
|
|
90
|
-
: value
|
|
91
|
-
? [value]
|
|
92
|
-
: [];
|
|
87
|
+
const selectedValues = useMemo(() => (multiSelect ? (values.length > 0 ? values : internalValues) : value ? [value] : []), [multiSelect, values, internalValues, value]);
|
|
93
88
|
const rootRef = useRef(null);
|
|
94
89
|
const searchInputRef = useRef(null);
|
|
95
90
|
/* ─── Favorites helpers ─── */
|
|
@@ -395,14 +390,14 @@ const NiceIconPicker = forwardRef(function NiceIconPicker({ icons, value = null,
|
|
|
395
390
|
}
|
|
396
391
|
return selectedEntry ? readableName(selectedEntry.name) : placeholder;
|
|
397
392
|
}, [multiSelect, selectedEntries, selectedEntry, placeholder]);
|
|
398
|
-
return (jsxs("div", { ref: rootRef, className: `ntd-picker${isOpen ? ' open' : ''}${disabled ? ' disabled' : ''}${multiSelect ? ' multi' : ''}${className ? ` ${className}` : ''}`, children: [jsxs("button", { type: "button", className: "ntd-picker-trigger", onClick: handleToggle, disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": isOpen, children: [jsx("span", { className: "ntd-picker-trigger-icon", children: selectedEntry ? (jsx(selectedEntry.Component, { size: triggerIconSize, variant: variant })) : multiSelect && selectedEntries.length > 1 ? (jsx("span", { className: "ntd-picker-multi-badge", children: selectedEntries.length })) : (
|
|
393
|
+
return (jsxs("div", { ref: rootRef, className: `ntd-picker${isOpen ? ' ntd-picker--open' : ''}${disabled ? ' ntd-picker--disabled' : ''}${multiSelect ? ' ntd-picker--multi' : ''}${className ? ` ${className}` : ''}`, children: [jsxs("button", { type: "button", className: "ntd-picker-trigger", onClick: handleToggle, disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": isOpen, children: [jsx("span", { className: "ntd-picker-trigger-icon", children: selectedEntry ? (jsx(selectedEntry.Component, { size: triggerIconSize, variant: variant })) : multiSelect && selectedEntries.length > 1 ? (jsx("span", { className: "ntd-picker-multi-badge", children: selectedEntries.length })) : (jsx(NtdGrid, { size: 16, variant: "outline" })) }), jsx("span", { className: `ntd-picker-trigger-label${!selectedEntry && selectedEntries.length === 0 ? ' ntd-picker-trigger-placeholder' : ''}`, children: triggerLabel }), jsx("span", { className: "ntd-picker-trigger-chevron", children: jsx(Chevron, {}) })] }), isOpen && (jsxs("div", { className: "ntd-picker-dropdown", role: "listbox", children: [jsxs("div", { className: "ntd-picker-search", children: [jsx("span", { className: "ntd-picker-search-icon", children: jsx(SearchIcon, {}) }), jsx("input", { ref: searchInputRef, type: "text", placeholder: "Search icons\u2026", value: search, onChange: (e) => setSearch(e.target.value), "aria-label": "Search icons" })] }), (allCategories.length > 1 || showFavorites || showHistory) && (jsxs("div", { className: "ntd-picker-tabs", role: "tablist", children: [jsx("button", { type: "button", className: `ntd-picker-tab${activeCategory === null ? ' ntd-picker-tab--active' : ''}`, onClick: () => setActiveCategory(null), role: "tab", "aria-selected": activeCategory === null, children: "All" }), showFavorites && (jsxs("button", { type: "button", className: `ntd-picker-tab ntd-picker-tab-special${activeCategory === '__favorites__' ? ' ntd-picker-tab--active' : ''}`, onClick: () => setActiveCategory('__favorites__'), role: "tab", "aria-selected": activeCategory === '__favorites__', title: "Favorites", children: [jsx(StarIcon, { filled: true }), " Favorites", favorites.length > 0 && (jsx("span", { className: "ntd-picker-tab-count", children: favorites.length }))] })), showHistory && history.length > 0 && (jsxs("button", { type: "button", className: `ntd-picker-tab ntd-picker-tab-special${activeCategory === '__history__' ? ' ntd-picker-tab--active' : ''}`, onClick: () => setActiveCategory('__history__'), role: "tab", "aria-selected": activeCategory === '__history__', title: "Recently used", children: [jsx(ClockIcon, {}), " Recent"] })), allCategories.map((cat) => (jsx("button", { type: "button", className: `ntd-picker-tab${activeCategory === cat ? ' ntd-picker-tab--active' : ''}`, onClick: () => setActiveCategory(cat), role: "tab", "aria-selected": activeCategory === cat, children: cat }, cat)))] })), jsx("div", { className: "ntd-picker-grid-wrap", ref: gridWrapRef, children: filtered.length === 0 ? (jsxs("div", { className: "ntd-picker-empty", children: [jsx("div", { className: "ntd-picker-empty-icon", children: jsx(NtdInbox, { size: 28, variant: "outline" }) }), activeCategory === '__favorites__'
|
|
399
394
|
? 'No favorites yet. Click the star icon to add.'
|
|
400
395
|
: activeCategory === '__history__'
|
|
401
396
|
? 'No recent icons.'
|
|
402
397
|
: 'No icons found'] })) : (jsxs(Fragment, { children: [virtualized && visibleRange.start > 0 && (jsx("div", { style: { height: Math.floor(visibleRange.start / 6) * 48 } })), Array.from(grouped.entries()).map(([category, entries]) => (jsxs("div", { children: [!activeCategory && !(activeCategory === null || activeCategory === void 0 ? void 0 : activeCategory.startsWith('__')) && (jsx("div", { className: "ntd-picker-category-label", children: category })), jsx("div", { className: "ntd-picker-grid", children: entries.map((entry) => {
|
|
403
398
|
const isSelected = selectedValues.includes(entry.name);
|
|
404
399
|
const isFavorite = favorites.includes(entry.name);
|
|
405
|
-
return (jsxs("button", { type: "button", className: `ntd-picker-cell${isSelected ? ' selected' : ''}${multiSelect ? ' multi-select' : ''}${enableDragAndDrop ? ' draggable' : ''}`, onClick: () => handleSelect(entry), "data-name": readableName(entry.name), role: "option", "aria-selected": isSelected, title: readableName(entry.name), draggable: enableDragAndDrop, onDragStart: enableDragAndDrop ? (e) => handleDragStart(entry, e) : undefined, onDragEnd: enableDragAndDrop ? (e) => handleDragEnd(entry, e) : undefined, children: [jsx(entry.Component, { size: gridIconSize, variant: variant }), multiSelect && isSelected && (jsx("span", { className: "ntd-picker-cell-check", children: jsx(CheckIcon, {}) })), showFavorites && (jsx("button", { type: "button", className: `ntd-picker-cell-fav${isFavorite ? ' active' : ''}`, onClick: (e) => handleFavoriteClick(e, entry.name), title: isFavorite ? 'Remove from favorites' : 'Add to favorites', children: jsx(StarIcon, { filled: isFavorite }) }))] }, entry.name));
|
|
400
|
+
return (jsxs("button", { type: "button", className: `ntd-picker-cell${isSelected ? ' ntd-picker-cell--selected' : ''}${multiSelect ? ' ntd-picker-cell--multi-select' : ''}${enableDragAndDrop ? ' ntd-picker-cell--draggable' : ''}`, onClick: () => handleSelect(entry), "data-name": readableName(entry.name), role: "option", "aria-selected": isSelected, title: readableName(entry.name), draggable: enableDragAndDrop, onDragStart: enableDragAndDrop ? (e) => handleDragStart(entry, e) : undefined, onDragEnd: enableDragAndDrop ? (e) => handleDragEnd(entry, e) : undefined, children: [jsx(entry.Component, { size: gridIconSize, variant: variant }), multiSelect && isSelected && (jsx("span", { className: "ntd-picker-cell-check", children: jsx(CheckIcon, {}) })), showFavorites && (jsx("button", { type: "button", className: `ntd-picker-cell-fav${isFavorite ? ' ntd-picker-cell-fav--active' : ''}`, onClick: (e) => handleFavoriteClick(e, entry.name), title: isFavorite ? 'Remove from favorites' : 'Add to favorites', children: jsx(StarIcon, { filled: isFavorite }) }))] }, entry.name));
|
|
406
401
|
}) })] }, category))), virtualized && visibleRange.end < filtered.length && (jsx("div", { style: { height: Math.ceil((filtered.length - visibleRange.end) / 6) * 48 } }))] })) }), jsxs("div", { className: "ntd-picker-footer", children: [jsxs("span", { className: "ntd-picker-count", children: [filtered.length, " icon", filtered.length !== 1 ? 's' : '', multiSelect && selectedValues.length > 0 && (jsxs(Fragment, { children: [" \u2022 ", selectedValues.length, " selected"] })), maxSelections && multiSelect && jsxs(Fragment, { children: [" (max ", maxSelections, ")"] })] }), clearable && selectedValues.length > 0 && (jsxs("button", { type: "button", className: "ntd-picker-clear", onClick: handleClear, children: ["Clear", multiSelect ? ' all' : ' selection'] })), multiSelect && (jsx("button", { type: "button", className: "ntd-picker-done", onClick: () => setIsOpen(false), children: "Done" }))] })] }))] }));
|
|
407
402
|
});
|
|
408
403
|
|
|
@@ -1,34 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useMemo, useCallback } from 'react';
|
|
3
|
-
import './icons/navigation.js';
|
|
4
3
|
import { NtdCheck } from './icons/actions.js';
|
|
5
|
-
import './icons/ui.js';
|
|
6
|
-
import './icons/sustainability.js';
|
|
7
|
-
import './icons/accessibility.js';
|
|
8
|
-
import './icons/legal.js';
|
|
9
|
-
import './icons/media.js';
|
|
10
|
-
import './icons/files.js';
|
|
11
|
-
import './icons/fun.js';
|
|
12
|
-
import './icons/weather.js';
|
|
13
|
-
import './icons/shapes.js';
|
|
14
|
-
import './icons/business.js';
|
|
15
|
-
import './icons/social.js';
|
|
16
|
-
import './icons/devtech.js';
|
|
17
|
-
import './icons/ecommerce.js';
|
|
18
|
-
import './icons/fintech.js';
|
|
19
|
-
import './icons/saas.js';
|
|
20
|
-
import './icons/smarthome.js';
|
|
21
|
-
import './icons/health.js';
|
|
22
|
-
import './icons/brand.js';
|
|
23
|
-
import './icons/gaming.js';
|
|
24
|
-
import './icons/ai.js';
|
|
25
|
-
import './icons/education.js';
|
|
26
|
-
import './icons/science.js';
|
|
27
|
-
import './icons/realestate.js';
|
|
28
|
-
import './icons/food.js';
|
|
29
|
-
import './icons/travel.js';
|
|
30
|
-
import './icons/sports.js';
|
|
31
|
-
import './icons/omniverk.js';
|
|
32
4
|
|
|
33
5
|
/* ══════════════════════════════════════════════════════════════════════════════
|
|
34
6
|
Constants
|
|
@@ -366,7 +338,12 @@ function NiceIconSetCreator({ icons, initialSelection, defaultConfig, onSelectio
|
|
|
366
338
|
URL.revokeObjectURL(url);
|
|
367
339
|
});
|
|
368
340
|
}, [creator]);
|
|
369
|
-
return (jsxs("div", { className: `nice-icon-set-creator ${className}`, style: styles.container, children: [jsxs("div", { style: styles.header, children: [jsx("h2", { style: styles.title, children: "Icon Set Creator" }), jsxs("div", { style: styles.stats, children: [creator.selectedCount, " / ", creator.items.length, " icons selected"] })] }), jsxs("div", { style: styles.content, children: [jsxs("div", { style: styles.configPanel, children: [jsx("h3", { style: styles.sectionTitle, children: "Configuration" }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Set Name" }), jsx("input", { type: "text", value: creator.config.name, onChange: (e) => creator.updateConfig({ name: e.target.value }), style: styles.input, placeholder: "MyIcons" })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Package Name" }), jsx("input", { type: "text", value: creator.config.packageName, onChange: (e) => creator.updateConfig({ packageName: e.target.value }), style: styles.input, placeholder: "@myproject/icons" })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Description" }), jsx("input", { type: "text", value: creator.config.description, onChange: (e) => creator.updateConfig({ description: e.target.value }), style: styles.input })] }), jsxs("div", { style: styles.fieldRow, children: [jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Version" }), jsx("input", { type: "text", value: creator.config.version, onChange: (e) => creator.updateConfig({ version: e.target.value }), style: styles.input })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "License" }), jsx("input", { type: "text", value: creator.config.license, onChange: (e) => creator.updateConfig({ license: e.target.value }), style: styles.input })] })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Export Format" }), jsxs("select", { value: creator.config.format, onChange: (e) => creator.updateConfig({ format: e.target.value }), style: styles.select, children: [jsx("option", { value: "esm", children: "ES Modules" }), jsx("option", { value: "cjs", children: "CommonJS" }), jsx("option", { value: "both", children: "Both" })] })] }), jsxs("div", { style: styles.checkboxGroup, children: [jsxs("label", { style: styles.checkbox, children: [jsx("input", { type: "checkbox", checked: creator.config.generateTypes, onChange: (e) => creator.updateConfig({ generateTypes: e.target.checked }) }), "Generate TypeScript types"] }), jsxs("label", { style: styles.checkbox, children: [jsx("input", { type: "checkbox", checked: creator.config.treeShaking, onChange: (e) => creator.updateConfig({ treeShaking: e.target.checked }) }), "Tree-shaking friendly"] }), jsxs("label", { style: styles.checkbox, children: [jsx("input", { type: "checkbox", checked: creator.config.includeMetadata, onChange: (e) => creator.updateConfig({ includeMetadata: e.target.checked }) }), "Include metadata"] })] }), jsxs("div", { style: styles.exportActions, children: [jsx("button", { onClick: handleExport, style: styles.primaryButton, children: "Preview Export" }), jsx("button", { onClick: handleDownloadZip, style: styles.secondaryButton, children: "Download Files" })] })] }), jsxs("div", { style: styles.selectionPanel, children: [jsxs("div", { style: styles.selectionHeader, children: [jsx("input", { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search icons...", style: styles.searchInput }), jsxs("select", { value: categoryFilter, onChange: (e) => setCategoryFilter(e.target.value), style: styles.categorySelect, children: [jsx("option", { value: "all", children: "All Categories" }), categories.map((cat) => (jsx("option", { value: cat, children: cat }, cat)))] })] }), jsxs("div", { style: styles.selectionActions, children: [jsx("button", { onClick: creator.selectAll, style: styles.smallButton, children: "Select All" }), jsx("button", { onClick: creator.deselectAll, style: styles.smallButton, children: "Deselect All" })] }), jsx("div", { style: styles.iconGrid, children: filteredItems.map((item) => (jsxs("div", { onClick: () => creator.toggleIcon(item.originalName),
|
|
341
|
+
return (jsxs("div", { className: `nice-icon-set-creator ${className}`, style: styles.container, children: [jsxs("div", { style: styles.header, children: [jsx("h2", { style: styles.title, children: "Icon Set Creator" }), jsxs("div", { style: styles.stats, children: [creator.selectedCount, " / ", creator.items.length, " icons selected"] })] }), jsxs("div", { style: styles.content, children: [jsxs("div", { style: styles.configPanel, children: [jsx("h3", { style: styles.sectionTitle, children: "Configuration" }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Set Name" }), jsx("input", { type: "text", value: creator.config.name, onChange: (e) => creator.updateConfig({ name: e.target.value }), style: styles.input, placeholder: "MyIcons" })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Package Name" }), jsx("input", { type: "text", value: creator.config.packageName, onChange: (e) => creator.updateConfig({ packageName: e.target.value }), style: styles.input, placeholder: "@myproject/icons" })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Description" }), jsx("input", { type: "text", value: creator.config.description, onChange: (e) => creator.updateConfig({ description: e.target.value }), style: styles.input })] }), jsxs("div", { style: styles.fieldRow, children: [jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Version" }), jsx("input", { type: "text", value: creator.config.version, onChange: (e) => creator.updateConfig({ version: e.target.value }), style: styles.input })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "License" }), jsx("input", { type: "text", value: creator.config.license, onChange: (e) => creator.updateConfig({ license: e.target.value }), style: styles.input })] })] }), jsxs("div", { style: styles.field, children: [jsx("label", { style: styles.fieldLabel, children: "Export Format" }), jsxs("select", { value: creator.config.format, onChange: (e) => creator.updateConfig({ format: e.target.value }), style: styles.select, children: [jsx("option", { value: "esm", children: "ES Modules" }), jsx("option", { value: "cjs", children: "CommonJS" }), jsx("option", { value: "both", children: "Both" })] })] }), jsxs("div", { style: styles.checkboxGroup, children: [jsxs("label", { style: styles.checkbox, children: [jsx("input", { type: "checkbox", checked: creator.config.generateTypes, onChange: (e) => creator.updateConfig({ generateTypes: e.target.checked }) }), "Generate TypeScript types"] }), jsxs("label", { style: styles.checkbox, children: [jsx("input", { type: "checkbox", checked: creator.config.treeShaking, onChange: (e) => creator.updateConfig({ treeShaking: e.target.checked }) }), "Tree-shaking friendly"] }), jsxs("label", { style: styles.checkbox, children: [jsx("input", { type: "checkbox", checked: creator.config.includeMetadata, onChange: (e) => creator.updateConfig({ includeMetadata: e.target.checked }) }), "Include metadata"] })] }), jsxs("div", { style: styles.exportActions, children: [jsx("button", { onClick: handleExport, style: styles.primaryButton, children: "Preview Export" }), jsx("button", { onClick: handleDownloadZip, style: styles.secondaryButton, children: "Download Files" })] })] }), jsxs("div", { style: styles.selectionPanel, children: [jsxs("div", { style: styles.selectionHeader, children: [jsx("input", { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search icons...", style: styles.searchInput }), jsxs("select", { value: categoryFilter, onChange: (e) => setCategoryFilter(e.target.value), style: styles.categorySelect, children: [jsx("option", { value: "all", children: "All Categories" }), categories.map((cat) => (jsx("option", { value: cat, children: cat }, cat)))] })] }), jsxs("div", { style: styles.selectionActions, children: [jsx("button", { onClick: creator.selectAll, style: styles.smallButton, children: "Select All" }), jsx("button", { onClick: creator.deselectAll, style: styles.smallButton, children: "Deselect All" })] }), jsx("div", { style: styles.iconGrid, children: filteredItems.map((item) => (jsxs("div", { role: "checkbox", "aria-checked": item.included, "aria-label": item.customName, tabIndex: 0, onClick: () => creator.toggleIcon(item.originalName), onKeyDown: (e) => {
|
|
342
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
343
|
+
e.preventDefault();
|
|
344
|
+
creator.toggleIcon(item.originalName);
|
|
345
|
+
}
|
|
346
|
+
}, style: {
|
|
370
347
|
...styles.iconItem,
|
|
371
348
|
borderColor: item.included ? '#3b82f6' : '#e5e7eb',
|
|
372
349
|
backgroundColor: item.included ? '#eff6ff' : '#fff',
|
package/dist/esm/NtdIconBadge.js
CHANGED
|
@@ -185,7 +185,8 @@ function injectStyles() {
|
|
|
185
185
|
* />
|
|
186
186
|
* ```
|
|
187
187
|
*/
|
|
188
|
-
const NtdBadge =
|
|
188
|
+
const NtdBadge = /* @__PURE__ */ Object.assign(
|
|
189
|
+
/* @__PURE__ */ forwardRef(({ icon: Icon, count = 0, maxCount = 99, showZero = false, position = 'top-right', variant = 'standard', badgeColor = '#ef4444', textColor = '#ffffff', animated = true, pulse = false, iconProps = {}, className, style, 'aria-label': ariaLabel, }, ref) => {
|
|
189
190
|
var _a, _b;
|
|
190
191
|
const [isEntering, setIsEntering] = useState(false);
|
|
191
192
|
const [countChanging, setCountChanging] = useState(false);
|
|
@@ -235,8 +236,7 @@ const NtdBadge = forwardRef(({ icon: Icon, count = 0, maxCount = 99, showZero =
|
|
|
235
236
|
backgroundColor: badgeColor,
|
|
236
237
|
color: textColor,
|
|
237
238
|
}, "aria-hidden": "true", children: variant !== 'dot' && displayCount }))] }));
|
|
238
|
-
});
|
|
239
|
-
NtdBadge.displayName = 'NtdBadge';
|
|
239
|
+
}), { displayName: 'NtdBadge' });
|
|
240
240
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
241
241
|
NtdStatusDot COMPONENT
|
|
242
242
|
───────────────────────────────────────────────────────────────────────────── */
|
|
@@ -255,7 +255,8 @@ NtdBadge.displayName = 'NtdBadge';
|
|
|
255
255
|
* <NtdStatusDot icon={NtdUser} status="away" position="bottom-right" />
|
|
256
256
|
* ```
|
|
257
257
|
*/
|
|
258
|
-
const NtdStatusDot =
|
|
258
|
+
const NtdStatusDot = /* @__PURE__ */ Object.assign(
|
|
259
|
+
/* @__PURE__ */ forwardRef(({ icon: Icon, status, statusColor, position = 'bottom-right', dotSize = 'md', animated = true, pulse = false, iconProps = {}, className, style, }, ref) => {
|
|
259
260
|
var _a, _b;
|
|
260
261
|
useEffect(() => {
|
|
261
262
|
injectStyles();
|
|
@@ -283,8 +284,7 @@ const NtdStatusDot = forwardRef(({ icon: Icon, status, statusColor, position = '
|
|
|
283
284
|
backgroundColor: resolvedColor,
|
|
284
285
|
color: resolvedColor,
|
|
285
286
|
}, "aria-hidden": "true" })] }));
|
|
286
|
-
});
|
|
287
|
-
NtdStatusDot.displayName = 'NtdStatusDot';
|
|
287
|
+
}), { displayName: 'NtdStatusDot' });
|
|
288
288
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
289
289
|
NtdIconOverlay COMPONENT
|
|
290
290
|
───────────────────────────────────────────────────────────────────────────── */
|
|
@@ -309,7 +309,8 @@ NtdStatusDot.displayName = 'NtdStatusDot';
|
|
|
309
309
|
* />
|
|
310
310
|
* ```
|
|
311
311
|
*/
|
|
312
|
-
const NtdIconOverlay =
|
|
312
|
+
const NtdIconOverlay = /* @__PURE__ */ Object.assign(
|
|
313
|
+
/* @__PURE__ */ forwardRef(({ icon: Icon, overlay, position = 'bottom-right', overlayScale = 0.5, overlayBg, circularBg = false, iconProps = {}, className, style, }, ref) => {
|
|
313
314
|
var _a, _b;
|
|
314
315
|
useEffect(() => {
|
|
315
316
|
injectStyles();
|
|
@@ -331,8 +332,7 @@ const NtdIconOverlay = forwardRef(({ icon: Icon, overlay, position = 'bottom-rig
|
|
|
331
332
|
height: overlaySize,
|
|
332
333
|
backgroundColor: overlayBg,
|
|
333
334
|
}, children: overlay })] }));
|
|
334
|
-
});
|
|
335
|
-
NtdIconOverlay.displayName = 'NtdIconOverlay';
|
|
335
|
+
}), { displayName: 'NtdIconOverlay' });
|
|
336
336
|
/**
|
|
337
337
|
* Stack two icons for composite imagery.
|
|
338
338
|
*
|
|
@@ -354,7 +354,8 @@ NtdIconOverlay.displayName = 'NtdIconOverlay';
|
|
|
354
354
|
* />
|
|
355
355
|
* ```
|
|
356
356
|
*/
|
|
357
|
-
const NtdIconStack =
|
|
357
|
+
const NtdIconStack = /* @__PURE__ */ Object.assign(
|
|
358
|
+
/* @__PURE__ */ forwardRef(({ base: BaseIcon, overlay: OverlayIcon, baseProps = {}, overlayProps = {}, position = 'bottom-right', overlayScale = 0.6, size, className, style, }, ref) => {
|
|
358
359
|
var _a, _b, _c;
|
|
359
360
|
const resolvedSize = size
|
|
360
361
|
? typeof size === 'number'
|
|
@@ -371,7 +372,6 @@ const NtdIconStack = forwardRef(({ base: BaseIcon, overlay: OverlayIcon, basePro
|
|
|
371
372
|
}, children: [jsx(BaseIcon, { ...baseProps, size: resolvedSize }), jsx("div", { className: "ntd-icon-overlay", style: {
|
|
372
373
|
...POSITION_STYLES[position],
|
|
373
374
|
}, children: jsx(OverlayIcon, { ...overlayProps, size: overlaySize }) })] }));
|
|
374
|
-
});
|
|
375
|
-
NtdIconStack.displayName = 'NtdIconStack';
|
|
375
|
+
}), { displayName: 'NtdIconStack' });
|
|
376
376
|
|
|
377
377
|
export { NtdBadge, NtdIconOverlay, NtdIconStack, NtdStatusDot };
|
package/dist/esm/NtdIconMorph.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef, useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { SIZE_MAP } from './types.js';
|
|
4
3
|
import { NtdCheck, NtdMinus, NtdPlus } from './icons/actions.js';
|
|
5
4
|
import { NtdPause, NtdPlay } from './icons/media.js';
|
|
6
5
|
import { NtdClose, NtdChevronDown, NtdChevronUp, NtdMenu } from './icons/navigation.js';
|
|
7
6
|
import { NtdMoon, NtdSun } from './icons/ui.js';
|
|
7
|
+
import { SIZE_MAP } from './types.js';
|
|
8
8
|
|
|
9
9
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
10
10
|
EASING FUNCTIONS
|
|
@@ -145,7 +145,8 @@ const morphStyles = `
|
|
|
145
145
|
* />
|
|
146
146
|
* ```
|
|
147
147
|
*/
|
|
148
|
-
const NtdIconMorph =
|
|
148
|
+
const NtdIconMorph = /* @__PURE__ */ Object.assign(
|
|
149
|
+
/* @__PURE__ */ forwardRef(({ from: FromIcon, to: ToIcon, morphed: controlledMorphed, trigger = 'none', duration = 300, easing = 'ease-in-out', size = 'md', variant = 'solid', primaryColor = 'currentColor', secondaryColor, onMorphStart, onMorphEnd, className, style, 'aria-label': ariaLabel, }, ref) => {
|
|
149
150
|
var _a, _b;
|
|
150
151
|
// Internal state for self-managed triggers
|
|
151
152
|
const [internalMorphed, setInternalMorphed] = useState(false);
|
|
@@ -237,9 +238,13 @@ const NtdIconMorph = forwardRef(({ from: FromIcon, to: ToIcon, morphed: controll
|
|
|
237
238
|
height: resolvedSize,
|
|
238
239
|
cursor: trigger !== 'none' ? 'pointer' : undefined,
|
|
239
240
|
...style,
|
|
240
|
-
}, onClick: handleClick,
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
}, onClick: handleClick, onKeyDown: (e) => {
|
|
242
|
+
if (trigger === 'click' && (e.key === 'Enter' || e.key === ' ')) {
|
|
243
|
+
e.preventDefault();
|
|
244
|
+
handleClick();
|
|
245
|
+
}
|
|
246
|
+
}, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, tabIndex: trigger === 'focus' || trigger === 'click' ? 0 : undefined, role: trigger !== 'none' ? 'button' : undefined, "aria-label": ariaLabel, "aria-pressed": trigger !== 'none' ? morphed : undefined, children: [jsx("div", { className: `ntd-morph-icon ${morphed ? 'ntd-morph-icon--inactive' : 'ntd-morph-icon--active'}`, style: transitionStyle, "aria-hidden": morphed, children: jsx(FromIcon, { ...iconProps }) }), jsx("div", { className: `ntd-morph-icon ${morphed ? 'ntd-morph-icon--active' : 'ntd-morph-icon--inactive'}`, style: transitionStyle, "aria-hidden": !morphed, children: jsx(ToIcon, { ...iconProps }) })] }));
|
|
247
|
+
}), { displayName: 'NtdIconMorph' });
|
|
243
248
|
/**
|
|
244
249
|
* Path-based morphing using CSS transitions on SVG path data.
|
|
245
250
|
* Requires browser support for CSS `d` property transitions (modern browsers).
|
|
@@ -254,7 +259,8 @@ NtdIconMorph.displayName = 'NtdIconMorph';
|
|
|
254
259
|
* />
|
|
255
260
|
* ```
|
|
256
261
|
*/
|
|
257
|
-
const NtdPathMorph =
|
|
262
|
+
const NtdPathMorph = /* @__PURE__ */ Object.assign(
|
|
263
|
+
/* @__PURE__ */ forwardRef(({ pair, morphed: controlledMorphed, trigger = 'none', duration = 300, easing = 'ease-in-out', size = 'md', color = 'currentColor', strokeWidth = 2, filled = false, onMorphStart, onMorphEnd, className, style, 'aria-label': ariaLabel, }, ref) => {
|
|
258
264
|
var _a, _b;
|
|
259
265
|
const [internalMorphed, setInternalMorphed] = useState(false);
|
|
260
266
|
const morphed = controlledMorphed !== null && controlledMorphed !== void 0 ? controlledMorphed : internalMorphed;
|
|
@@ -310,8 +316,12 @@ const NtdPathMorph = forwardRef(({ pair, morphed: controlledMorphed, trigger = '
|
|
|
310
316
|
}, onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, role: trigger !== 'none' ? 'button' : 'img', "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : `${pair} icon`, "aria-pressed": trigger !== 'none' ? morphed : undefined, children: jsx("path", { d: currentPath, fill: filled ? color : 'none', stroke: filled ? 'none' : color, strokeWidth: filled ? 0 : strokeWidth, strokeLinecap: "round", strokeLinejoin: "round", style: {
|
|
311
317
|
transition: `d ${duration}ms ${resolvedEasing}, fill ${duration}ms ${resolvedEasing}, stroke ${duration}ms ${resolvedEasing}`,
|
|
312
318
|
} }) }));
|
|
313
|
-
});
|
|
314
|
-
|
|
319
|
+
}), { displayName: 'NtdPathMorph' });
|
|
320
|
+
/* ────────────────────────────────────────────────────────────────────────────
|
|
321
|
+
PREDEFINED MORPH PAIR COMPONENT
|
|
322
|
+
Convenience wrapper for common morphing patterns
|
|
323
|
+
───────────────────────────────────────────────────────────────────────────── */
|
|
324
|
+
// Import icons lazily for predefined pairs
|
|
315
325
|
const ICON_PAIRS = {
|
|
316
326
|
'menu-close': { from: NtdMenu, to: NtdClose },
|
|
317
327
|
'play-pause': { from: NtdPlay, to: NtdPause },
|
|
@@ -335,15 +345,15 @@ const ICON_PAIRS = {
|
|
|
335
345
|
* <NtdMorphPair pair="sun-moon" trigger="click" />
|
|
336
346
|
* ```
|
|
337
347
|
*/
|
|
338
|
-
const NtdMorphPair =
|
|
348
|
+
const NtdMorphPair = /* @__PURE__ */ Object.assign(
|
|
349
|
+
/* @__PURE__ */ forwardRef(({ pair, ...props }, ref) => {
|
|
339
350
|
const iconPair = ICON_PAIRS[pair];
|
|
340
351
|
if (!iconPair) {
|
|
341
352
|
console.warn(`NtdMorphPair: Unknown pair "${pair}"`);
|
|
342
353
|
return null;
|
|
343
354
|
}
|
|
344
355
|
return jsx(NtdIconMorph, { ref: ref, from: iconPair.from, to: iconPair.to, ...props });
|
|
345
|
-
});
|
|
346
|
-
NtdMorphPair.displayName = 'NtdMorphPair';
|
|
356
|
+
}), { displayName: 'NtdMorphPair' });
|
|
347
357
|
/**
|
|
348
358
|
* Hook for managing morph state with animation awareness.
|
|
349
359
|
*
|
|
@@ -41,7 +41,8 @@ function interpolateSegments(from, to, t) {
|
|
|
41
41
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
42
42
|
COMPONENT
|
|
43
43
|
───────────────────────────────────────────────────────────────────────────── */
|
|
44
|
-
const NtdStateMorph =
|
|
44
|
+
const NtdStateMorph = /* @__PURE__ */ Object.assign(
|
|
45
|
+
/* @__PURE__ */ forwardRef(({ states, currentState, fills, strokes, strokeWidth = 2, duration = 300, easing: _easing = 'ease-in-out', size = 'md', viewBox = '0 0 24 24', className, style, 'aria-label': ariaLabel, onTransitionEnd, }, ref) => {
|
|
45
46
|
var _a;
|
|
46
47
|
const svgRef = useRef(null);
|
|
47
48
|
const animRef = useRef(0);
|
|
@@ -109,8 +110,7 @@ const NtdStateMorph = forwardRef(({ states, currentState, fills, strokes, stroke
|
|
|
109
110
|
getSvgElement: () => svgRef.current,
|
|
110
111
|
}));
|
|
111
112
|
return (jsx("svg", { ref: svgRef, xmlns: "http://www.w3.org/2000/svg", viewBox: viewBox, width: resolvedSize, height: resolvedSize, fill: "none", className: className, style: style, "aria-label": ariaLabel, role: ariaLabel ? 'img' : undefined, children: jsx("path", { d: currentPath, fill: currentFill, stroke: currentStroke, strokeWidth: strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
112
|
-
});
|
|
113
|
-
NtdStateMorph.displayName = 'NtdStateMorph';
|
|
113
|
+
}), { displayName: 'NtdStateMorph' });
|
|
114
114
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
115
115
|
COLOR INTERPOLATION
|
|
116
116
|
───────────────────────────────────────────────────────────────────────────── */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { useState, useRef, useMemo, useCallback, useEffect, forwardRef, useImperativeHandle } from 'react';
|
|
3
3
|
|
|
4
4
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
5
5
|
2. HELPER FUNCTIONS
|
|
@@ -237,7 +237,7 @@ function useAnimationSequence(config) {
|
|
|
237
237
|
* </AnimationController>
|
|
238
238
|
* ```
|
|
239
239
|
*/
|
|
240
|
-
const AnimationController = forwardRef(function AnimationController(props, ref) {
|
|
240
|
+
const AnimationController = /* @__PURE__ */ forwardRef(function AnimationController(props, ref) {
|
|
241
241
|
const { children, animation, autoPlay = false, playState: externalPlayState, onStart, onEnd, onStepChange, onPause, onResume, className, style, } = props;
|
|
242
242
|
// Determine if sequence or single animation
|
|
243
243
|
const isSequence = isSequenceConfig(animation);
|
|
@@ -422,7 +422,7 @@ const AnimationController = forwardRef(function AnimationController(props, ref)
|
|
|
422
422
|
* </InteractiveIcon>
|
|
423
423
|
* ```
|
|
424
424
|
*/
|
|
425
|
-
const InteractiveIcon = forwardRef(function InteractiveIcon(props, ref) {
|
|
425
|
+
const InteractiveIcon = /* @__PURE__ */ forwardRef(function InteractiveIcon(props, ref) {
|
|
426
426
|
const { children, config, disabled = false, onInteractionStart, onInteractionEnd, className, style, } = props;
|
|
427
427
|
const [isActive, setIsActive] = useState(false);
|
|
428
428
|
const [isLeaving, setIsLeaving] = useState(false);
|
|
@@ -536,7 +536,14 @@ const InteractiveIcon = forwardRef(function InteractiveIcon(props, ref) {
|
|
|
536
536
|
display: 'inline-flex',
|
|
537
537
|
cursor: disabled ? 'default' : config.trigger === 'click' ? 'pointer' : undefined,
|
|
538
538
|
...style,
|
|
539
|
-
}, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: handleClick,
|
|
539
|
+
}, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: handleClick, onKeyDown: handleClick
|
|
540
|
+
? (e) => {
|
|
541
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
542
|
+
e.preventDefault();
|
|
543
|
+
handleClick();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
: undefined, onFocus: handleFocus, onBlur: handleBlur, tabIndex: config.trigger === 'focus' || config.trigger === 'click' ? 0 : undefined, role: config.trigger === 'click' ? 'button' : undefined, children: animatedChild }));
|
|
540
547
|
});
|
|
541
548
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
542
549
|
6. UTILITY FUNCTIONS
|