@nice2dev/icons 1.3.4 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +31 -0
  3. package/dist/cjs/NiceIconStacker.js +120 -0
  4. package/dist/cjs/client.js +3 -0
  5. package/dist/cjs/createIcon.js +21 -3
  6. package/dist/cjs/icons/actions.js +25 -4
  7. package/dist/cjs/icons/ai.js +3 -0
  8. package/dist/cjs/icons/files.js +24 -7
  9. package/dist/cjs/icons/index.js +2 -2
  10. package/dist/cjs/icons/shapes.js +2 -10
  11. package/dist/cjs/icons/sustainability.js +2 -11
  12. package/dist/cjs/icons/ui.js +6 -0
  13. package/dist/cjs/icons/weather.js +3 -0
  14. package/dist/cjs/index.js +5 -2
  15. package/dist/cjs/nicetodev-icons.css +1 -1
  16. package/dist/cjs/stacking.js +100 -0
  17. package/dist/esm/NiceIconStacker.js +117 -0
  18. package/dist/esm/client.js +1 -0
  19. package/dist/esm/createIcon.js +22 -4
  20. package/dist/esm/icons/actions.js +25 -4
  21. package/dist/esm/icons/ai.js +3 -1
  22. package/dist/esm/icons/files.js +24 -7
  23. package/dist/esm/icons/index.js +4 -4
  24. package/dist/esm/icons/shapes.js +3 -10
  25. package/dist/esm/icons/sustainability.js +2 -10
  26. package/dist/esm/icons/ui.js +6 -0
  27. package/dist/esm/icons/weather.js +3 -1
  28. package/dist/esm/index.js +5 -4
  29. package/dist/esm/nicetodev-icons.css +1 -1
  30. package/dist/esm/stacking.js +92 -0
  31. package/dist/types/NiceIconStacker.d.ts +50 -0
  32. package/dist/types/client.d.ts +2 -0
  33. package/dist/types/createIcon.d.ts +5 -0
  34. package/dist/types/icons/ai.d.ts +2 -0
  35. package/dist/types/icons/index.d.ts +4 -4
  36. package/dist/types/icons/shapes.d.ts +0 -1
  37. package/dist/types/icons/sustainability.d.ts +0 -1
  38. package/dist/types/icons/weather.d.ts +2 -0
  39. package/dist/types/index.d.ts +3 -1
  40. package/dist/types/stacking.d.ts +41 -0
  41. package/dist/types/types.d.ts +23 -0
  42. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # @nice2dev/icons — Changelog
2
2
 
3
+ ## 1.3.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 2b49cd7: Icon browser feedback, round 36:
8
+
9
+ - `NtdMonitor`: neck and base twice the stroke width in every variant but `outline`; the base
10
+ 30% wider. Vivid's stand is secondary (it had a fixed `#3B82F6`).
11
+ - `NtdPieChart`: the larger part is a proper three-quarter sector from the centre (it was a segment
12
+ cut off by a chord). The two sectors have a gap between them; duotone uses fills only.
13
+ - `NtdCopy`:
14
+ - the front, filled sheet at the top right;
15
+ - the back sheet's line stops 1 short of it at any stroke width;
16
+ - `sharp` draws the back sheet with square corners;
17
+ - duotone uses fills only.
18
+ - `NtdStar4` is now a deprecated alias of `NtdSparkle`, and `NtdHydropower` of `NtdDroplet`. Both
19
+ are duplicates; the old names still work.
20
+
21
+ - 16d420b: Stack icons by nesting them, and build stacks in NiceIconStacker:
22
+
23
+ - An icon draws its children in its own SVG:
24
+ `<NtdSquare><NtdStar stackAlign="center">1</NtdStar></NtdSquare>`.
25
+ - **Child icons** sit where `stackAlign` says: `center`, an edge or a corner. `stackSize` sets
26
+ their share of the parent (default 0.6 centred, 0.5 elsewhere).
27
+ - **Text children** are centred on the icon's visual centre. `NtdStar`, `NtdHeart`, `NtdShield`
28
+ and `NtdTriangle` have their own centre (`textCenter` in `createIcon`). `textColor` and
29
+ `textSize` override the text's colour and size.
30
+ - **Colours** follow the parent: a filled parent cuts centred and edge content out (the parent's
31
+ accent); a corner badge keeps the parent's colours on an accent-coloured gap. Colours given on
32
+ a child win.
33
+ - `NiceIconStacker`:
34
+ - lists the base icon and the icons stacked in it, each with its position, size and text;
35
+ - adds the `current` icon, removes one or clears the stack;
36
+ - previews the stack at three sizes and writes its JSX (`niceIconStackCode`).
37
+ - New translation keys `iconStacker.*` (en, pl, de, fr, es, uk).
38
+
3
39
  ## 1.3.4
4
40
 
5
41
  ### Patch Changes
package/README.md CHANGED
@@ -205,6 +205,37 @@ See [Full Animation Catalog](#full-animation-catalog) for the complete list.
205
205
 
206
206
  ---
207
207
 
208
+ ### Stacking icons
209
+
210
+ Nest icons to stack them in one SVG. A child icon sits where its `stackAlign` says, and text is
211
+ centred on the icon:
212
+
213
+ ```tsx
214
+ <NtdSquare variant="solid">
215
+ <NtdStar stackAlign="center">1</NtdStar>
216
+ </NtdSquare>
217
+
218
+ <NtdFolder>
219
+ <NtdPlus stackAlign="top-right" />
220
+ </NtdFolder>
221
+
222
+ <NtdCircle>42</NtdCircle>
223
+ ```
224
+
225
+ - **`stackAlign`:** `center` (default), `top`, `bottom`, `left`, `right`, `top-left`,
226
+ `top-right`, `bottom-left`, `bottom-right`.
227
+ - **`stackSize`:** the child's share of its parent. Default `0.6` centred, `0.5` elsewhere.
228
+ - **Colours** follow the parent unless the child sets its own:
229
+ - In the centre or at an edge, a filled parent cuts the content out. The child takes the
230
+ parent's accent and its text the parent's primary. On `outline` / `wireframe` everything stays
231
+ in primary.
232
+ - A corner badge keeps the parent's colours and sits on an accent-coloured gap.
233
+ - **Text:** `textColor` and `textSize` override the text's colour and size.
234
+ - **Builder:** `NiceIconStacker` builds a stack interactively and writes the JSX
235
+ (`niceIconStackCode`).
236
+
237
+ ---
238
+
208
239
  ### Gradient Fills
209
240
 
210
241
  Apply gradient fills using the `gradient` prop with one of 12 built-in presets:
@@ -0,0 +1,120 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var uiCore = require('@nice2dev/ui-core');
5
+ var React = require('react');
6
+ var actions = require('./icons/actions.js');
7
+ var stacking = require('./stacking.js');
8
+
9
+ const ALIGNS = [
10
+ 'center',
11
+ 'top',
12
+ 'bottom',
13
+ 'left',
14
+ 'right',
15
+ 'top-left',
16
+ 'top-right',
17
+ 'bottom-left',
18
+ 'bottom-right',
19
+ ];
20
+ const PREVIEW_SIZES = [96, 48, 24];
21
+ const NO_LAYERS = [];
22
+ /** The stack as JSX, the base wrapping its layers. */
23
+ function niceIconStackCode(layers) {
24
+ const [base, ...rest] = layers;
25
+ if (!base) {
26
+ return '';
27
+ }
28
+ const baseAttrs = base.variant ? ` variant="${base.variant}"` : '';
29
+ if (rest.length === 0) {
30
+ return base.text
31
+ ? `<${base.icon}${baseAttrs}>${base.text}</${base.icon}>`
32
+ : `<${base.icon}${baseAttrs} />`;
33
+ }
34
+ const lines = rest.map((l) => {
35
+ var _a;
36
+ const attrs = [
37
+ `stackAlign="${(_a = l.align) !== null && _a !== void 0 ? _a : 'center'}"`,
38
+ l.size !== undefined ? `stackSize={${l.size}}` : '',
39
+ l.variant && l.variant !== base.variant ? `variant="${l.variant}"` : '',
40
+ ]
41
+ .filter(Boolean)
42
+ .join(' ');
43
+ return l.text ? ` <${l.icon} ${attrs}>${l.text}</${l.icon}>` : ` <${l.icon} ${attrs} />`;
44
+ });
45
+ return [
46
+ `<${base.icon}${baseAttrs}>`,
47
+ ...(base.text ? [` ${base.text}`] : []),
48
+ ...lines,
49
+ `</${base.icon}>`,
50
+ ].join('\n');
51
+ }
52
+ /**
53
+ * NiceIconStacker (1.3.5) — builds an icon stack: the base icon and the icons stacked in it, each
54
+ * with its position, size and text, shown live at three sizes and as the JSX that draws it. Icons
55
+ * come in through `current` (the "add" button) and leave one by one or all at once.
56
+ */
57
+ function NiceIconStacker({ icons, layers: layersProp, defaultLayers, onLayersChange, current, previewProps, className, }) {
58
+ var _a;
59
+ const { t } = uiCore.useNiceTranslation();
60
+ const [layers, setLayers] = uiCore.useControllableState({
61
+ value: layersProp,
62
+ defaultValue: defaultLayers,
63
+ fallbackValue: NO_LAYERS,
64
+ onChange: onLayersChange,
65
+ componentName: 'NiceIconStacker',
66
+ });
67
+ const nextId = React.useRef(0);
68
+ const [copied, setCopied] = React.useState(false);
69
+ const resolve = React.useCallback((name) => (typeof icons === 'function' ? icons(name) : icons[name]), [icons]);
70
+ const [base, ...rest] = layers;
71
+ const code = React.useMemo(() => niceIconStackCode(layers), [layers]);
72
+ const update = (id, patch) => setLayers((prev) => prev.map((l) => (l.id === id ? { ...l, ...patch } : l)));
73
+ const add = () => {
74
+ if (!current) {
75
+ return;
76
+ }
77
+ nextId.current += 1;
78
+ const layer = {
79
+ id: `${current.icon}-${nextId.current}`,
80
+ icon: current.icon,
81
+ variant: current.variant,
82
+ };
83
+ setLayers((prev) => [...prev, layer]);
84
+ };
85
+ const remove = (id) => setLayers((prev) => prev.filter((l) => l.id !== id));
86
+ const clear = () => setLayers(NO_LAYERS);
87
+ const copy = () => {
88
+ var _a;
89
+ void ((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText(code).then(() => {
90
+ setCopied(true);
91
+ window.setTimeout(() => setCopied(false), 1500);
92
+ }));
93
+ };
94
+ const renderStack = (size) => {
95
+ var _a;
96
+ const Base = base ? resolve(base.icon) : undefined;
97
+ if (!base || !Base) {
98
+ return null;
99
+ }
100
+ return (jsxRuntime.jsxs(Base, { ...previewProps, variant: (_a = base.variant) !== null && _a !== void 0 ? _a : previewProps === null || previewProps === void 0 ? void 0 : previewProps.variant, size: size, title: base.icon, children: [base.text, rest.map((l) => {
101
+ var _a;
102
+ const Layer = resolve(l.icon);
103
+ return Layer ? (jsxRuntime.jsx(Layer, { stackAlign: (_a = l.align) !== null && _a !== void 0 ? _a : 'center', stackSize: l.size, variant: l.variant !== base.variant ? l.variant : undefined, children: l.text }, l.id)) : null;
104
+ })] }));
105
+ };
106
+ return (jsxRuntime.jsxs("div", { className: ['nice-icon-stacker', className].filter(Boolean).join(' '), children: [jsxRuntime.jsxs("div", { className: "nice-icon-stacker__toolbar", children: [jsxRuntime.jsxs("button", { type: "button", onClick: add, disabled: !current, children: [jsxRuntime.jsx(actions.NtdPlus, { size: 14 }), ' ', t('iconStacker.add', 'Add {icon} to the stack').replace('{icon}', (_a = current === null || current === void 0 ? void 0 : current.icon) !== null && _a !== void 0 ? _a : '')] }), jsxRuntime.jsxs("button", { type: "button", onClick: clear, disabled: layers.length === 0, children: [jsxRuntime.jsx(actions.NtdTrash, { size: 14 }), " ", t('iconStacker.clear', 'Clear the stack')] })] }), layers.length === 0 ? (jsxRuntime.jsx("p", { className: "nice-icon-stacker__empty", children: t('iconStacker.empty', 'The stack is empty. Add an icon to start one.') })) : (jsxRuntime.jsxs("div", { className: "nice-icon-stacker__body", children: [jsxRuntime.jsx("div", { className: "nice-icon-stacker__preview", "aria-label": t('iconStacker.preview', 'Preview'), role: "group", children: PREVIEW_SIZES.map((s) => (jsxRuntime.jsxs("span", { className: "nice-icon-stacker__preview-cell", children: [renderStack(s), jsxRuntime.jsxs("small", { children: [s, "px"] })] }, s))) }), jsxRuntime.jsx("ol", { className: "nice-icon-stacker__layers", "aria-label": t('iconStacker.layers', 'Layers'), children: layers.map((l, i) => {
107
+ var _a, _b, _c;
108
+ const Icon = resolve(l.icon);
109
+ const isBase = i === 0;
110
+ const align = (_a = l.align) !== null && _a !== void 0 ? _a : 'center';
111
+ const share = (_b = l.size) !== null && _b !== void 0 ? _b : stacking.defaultStackSize(align);
112
+ return (jsxRuntime.jsxs("li", { className: "nice-icon-stacker__layer", children: [jsxRuntime.jsx("span", { className: "nice-icon-stacker__layer-icon", children: Icon ? jsxRuntime.jsx(Icon, { size: 24, variant: l.variant }) : null }), jsxRuntime.jsxs("span", { className: "nice-icon-stacker__layer-name", children: [l.icon, isBase && (jsxRuntime.jsx("span", { className: "nice-icon-stacker__badge", children: t('iconStacker.base', 'Base') }))] }), !isBase && (jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.align', 'Position') }), jsxRuntime.jsx("select", { value: align, onChange: (e) => update(l.id, { align: e.target.value }), children: ALIGNS.map((a) => (jsxRuntime.jsx("option", { value: a, children: a }, a))) })] })), !isBase && (jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.size', 'Size') }), jsxRuntime.jsx("input", { type: "range", min: 0.2, max: 1, step: 0.05, value: share, onChange: (e) => update(l.id, { size: Number(e.target.value) }) }), jsxRuntime.jsxs("output", { children: [Math.round(share * 100), "%"] })] })), jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.text', 'Text') }), jsxRuntime.jsx("input", { type: "text", value: (_c = l.text) !== null && _c !== void 0 ? _c : '', maxLength: 4, onChange: (e) => update(l.id, { text: e.target.value || undefined }) })] }), jsxRuntime.jsx("button", { type: "button", className: "nice-icon-stacker__remove", onClick: () => remove(l.id), "aria-label": t('iconStacker.remove', 'Remove {icon}').replace('{icon}', l.icon), title: t('iconStacker.remove', 'Remove {icon}').replace('{icon}', l.icon), children: jsxRuntime.jsx(actions.NtdTrash, { size: 14 }) })] }, l.id));
113
+ }) }), jsxRuntime.jsxs("div", { className: "nice-icon-stacker__code", children: [jsxRuntime.jsx("pre", { children: code }), jsxRuntime.jsxs("button", { type: "button", onClick: copy, children: [copied ? jsxRuntime.jsx(actions.NtdCheck, { size: 14 }) : jsxRuntime.jsx(actions.NtdCopy, { size: 14 }), ' ', copied ? t('iconStacker.copied', 'Copied') : t('iconStacker.copy', 'Copy the code')] })] })] }))] }));
114
+ }
115
+ if (process.env.NODE_ENV !== 'production') {
116
+ NiceIconStacker.displayName = 'NiceIconStacker';
117
+ }
118
+
119
+ exports.NiceIconStacker = NiceIconStacker;
120
+ exports.niceIconStackCode = niceIconStackCode;
@@ -2,6 +2,7 @@
2
2
 
3
3
  var animationControls = require('./animationControls.js');
4
4
  var NiceIconPicker = require('./NiceIconPicker.js');
5
+ var NiceIconStacker = require('./NiceIconStacker.js');
5
6
  var NtdIconMorph = require('./NtdIconMorph.js');
6
7
  var NtdIconBadge = require('./NtdIconBadge.js');
7
8
  var smilAnimations = require('./smilAnimations.js');
@@ -18,6 +19,8 @@ exports.createHoverAnimation = animationControls.createHoverAnimation;
18
19
  exports.createVisibilityAnimation = animationControls.createVisibilityAnimation;
19
20
  exports.useAnimationSequence = animationControls.useAnimationSequence;
20
21
  exports.NiceIconPicker = NiceIconPicker.NiceIconPicker;
22
+ exports.NiceIconStacker = NiceIconStacker.NiceIconStacker;
23
+ exports.niceIconStackCode = NiceIconStacker.niceIconStackCode;
21
24
  exports.NtdIconMorph = NtdIconMorph.NtdIconMorph;
22
25
  exports.NtdMorphPair = NtdIconMorph.NtdMorphPair;
23
26
  exports.NtdPathMorph = NtdIconMorph.NtdPathMorph;
@@ -4,6 +4,7 @@ var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
  var sharpen = require('./sharpen.js');
6
6
  var smilAnimations = require('./smilAnimations.js');
7
+ var stacking = require('./stacking.js');
7
8
  var types = require('./types.js');
8
9
 
9
10
  /* ── Dark mode detection hook ───────────────────────── */
@@ -27,6 +28,7 @@ function subscribeColorScheme(callback) {
27
28
  function useColorScheme() {
28
29
  return React.useSyncExternalStore(subscribeColorScheme, getColorScheme, () => 'light');
29
30
  }
31
+ const BOX_CENTER = [12, 12];
30
32
  /**
31
33
  * Factory function that creates a React icon component from SVG path renderers.
32
34
  *
@@ -113,10 +115,12 @@ function renderCutoutShape(shape, fill, maskId) {
113
115
  }
114
116
  }
115
117
  function createIcon(options) {
116
- const { displayName, viewBox = '0 0 24 24', paths } = options;
118
+ const { displayName, viewBox = '0 0 24 24', paths, textCenter = BOX_CENTER } = options;
117
119
  const Icon = React.forwardRef(({ size = 'md', variant = 'solid', cutoutShape = 'rounded-square', color, lightColor, darkColor, primaryColor: propPrimaryColor = 'currentColor', secondaryColor, accentColor, primaryOpacity = 1, secondaryOpacity = 0.4, accentOpacity = 1, strokeWidth = 2, strokeLinecap: propLinecap, strokeLinejoin: propLinejoin, animation, animationDuration, smilAnimation, smilDuration = 1, smilRepeatCount = 'indefinite', smilEasing = 'ease-in-out', smilDelay = 0, gradient, gradientType = 'linear', gradientAngle = 135, gradientAnimation,
118
120
  // Transform props
119
- rotate, flipX, flipY, scale, transition, transformOrigin = 'center center', title, className, style, ...rest }, ref) => {
121
+ rotate, flipX, flipY, scale, transition, transformOrigin = 'center center',
122
+ // stacking (1.3.5): the parent icon reads a child's own align / size from its props
123
+ children, stackAlign: _stackAlign, stackSize: _stackSize, textColor, textSize, title, className, style, ...rest }, ref) => {
120
124
  var _a, _b, _c, _d, _e, _f, _g;
121
125
  const resolvedSize = typeof size === 'number' ? size : ((_a = types.SIZE_MAP[size]) !== null && _a !== void 0 ? _a : 24);
122
126
  const gradId = React.useId();
@@ -225,7 +229,19 @@ function createIcon(options) {
225
229
  : variant === 'wireframe'
226
230
  ? sharpen.wireTree(renderer(renderProps), effectivePrimary)
227
231
  : renderer(renderProps);
228
- const iconContent = variant === 'mini' ? (jsxRuntime.jsx("g", { transform: `translate(${center.x} ${center.y}) scale(${sharpen.MINI_SCALE}) translate(${-center.x} ${-center.y})`, children: rendered })) : (rendered);
232
+ // Children stacked in the icon (1.3.5) — drawn as they are, not re-drawn as the variant.
233
+ const stacked = stacking.renderStackChildren(children, {
234
+ variant,
235
+ primaryColor: effectivePrimary,
236
+ accentColor: resolvedAccent,
237
+ tileColor: gradient ? effectivePrimary : resolvedSecondary,
238
+ strokeWidth,
239
+ textCenter,
240
+ textColor,
241
+ textSize,
242
+ });
243
+ const drawn = stacked ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [rendered, stacked] })) : (rendered);
244
+ const iconContent = variant === 'mini' ? (jsxRuntime.jsx("g", { transform: `translate(${center.x} ${center.y}) scale(${sharpen.MINI_SCALE}) translate(${-center.x} ${-center.y})`, children: drawn })) : (drawn);
229
245
  return (jsxRuntime.jsxs("svg", { ref: ref, xmlns: "http://www.w3.org/2000/svg", viewBox: viewBox, width: resolvedSize, height: resolvedSize, fill: "none", strokeLinecap: strokeLinecap, strokeLinejoin: strokeLinejoin, className: classes, style: animStyle, role: title ? 'img' : 'presentation', "aria-hidden": title ? undefined : true, "aria-label": title, ...rest, children: [title && jsxRuntime.jsx("title", { children: title }), gradient && (jsxRuntime.jsx("defs", { children: renderGradientDef(gradId, gradient, gradientType, gradientAngle, gradientAnimation) })), is3d && jsxRuntime.jsx("defs", { children: render3dFilterDef(filterId) }), isCutout && (jsxRuntime.jsx("defs", { children: jsxRuntime.jsxs("mask", { id: maskId, children: [jsxRuntime.jsx("rect", { x: "0", y: "0", width: "24", height: "24", fill: "white" }), jsxRuntime.jsx("g", { transform: "translate(12,12) scale(0.8) translate(-12,-12)", children: paths.solid({
230
246
  ...renderProps,
231
247
  primaryColor: 'black',
@@ -238,6 +254,8 @@ function createIcon(options) {
238
254
  }) })] }) })), smilAnimation ? (needsSmilScaleWrapper ? (jsxRuntime.jsxs("g", { transform: `translate(${center.x}, ${center.y})`, filter: is3d ? `url(#${filterId})` : undefined, children: [jsxRuntime.jsx("g", { transform: `translate(-${center.x}, -${center.y})`, children: iconContent }), smilAnimationElements] })) : (jsxRuntime.jsxs("g", { filter: is3d ? `url(#${filterId})` : undefined, children: [iconContent, smilAnimationElements] }))) : is3d ? (jsxRuntime.jsx("g", { filter: `url(#${filterId})`, children: iconContent })) : (iconContent)] }));
239
255
  });
240
256
  Icon.displayName = displayName;
257
+ // lets a parent icon tell this one among its children (stacking, 1.3.5)
258
+ Icon[stacking.NTD_ICON_MARK] = true;
241
259
  return Icon;
242
260
  }
243
261
 
@@ -121,13 +121,34 @@ const NtdShare = /* @__PURE__ */ createIcon.createIcon({
121
121
  vivid: ({ primaryColor, secondaryColor, strokeWidth }) => shareFilled(primaryColor, secondaryColor, strokeWidth),
122
122
  },
123
123
  });
124
+ // NtdCopy: the front sheet at the top right (it was at the bottom right), the back one showing at
125
+ // the bottom left as a line that stops 1 short of the front — closer than before. The gap is
126
+ // worked out from the stroke width, so it stays the same at any weight; `sharp` draws the back
127
+ // sheet with square corners (the derived one kept their arcs). Duotone, fills only: the back sheet
128
+ // secondary under the primary front one; vivid: the back line secondary.
129
+ const COPY_FRONT = { x: 8.5, y: 3, width: 12.5, height: 12.5, rx: 2.5 };
130
+ const COPY_BACK = { x: 3, y: 8.5, width: 12.5, height: 12.5, rx: 2.5 };
131
+ /** What shows of the back sheet: its edges outside the front one, `gap` short of it. */
132
+ function copyBack(gap, square = false) {
133
+ const top = COPY_FRONT.x - gap;
134
+ const right = COPY_FRONT.y + COPY_FRONT.height + gap;
135
+ return square
136
+ ? `M${top} 8.5H3V21h12.5V${right}`
137
+ : `M${top} 8.5H5.5a2.5 2.5 0 00-2.5 2.5v7.5a2.5 2.5 0 002.5 2.5h7.5a2.5 2.5 0 002.5-2.5V${right}`;
138
+ }
139
+ /** The front sheet filled and the back one as a line 1 short of it (past its round cap). */
140
+ function copyFilled(front, back, strokeWidth, square = false) {
141
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...COPY_FRONT, fill: front }), jsxRuntime.jsx("path", { d: copyBack(1 + strokeWidth / 2, square), stroke: back, strokeWidth: strokeWidth, fill: "none" })] }));
142
+ }
124
143
  const NtdCopy = /* @__PURE__ */ createIcon.createIcon({
125
144
  displayName: 'NtdCopy',
126
145
  paths: {
127
- solid: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "9", y: "9", width: "12", height: "12", rx: "2.5", fill: primaryColor }), jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1", stroke: primaryColor, strokeWidth: strokeWidth })] })),
128
- outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "9", y: "9", width: "12", height: "12", rx: "2.5", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1", stroke: primaryColor, strokeWidth: strokeWidth })] })),
129
- duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "2", y: "2", width: "13", height: "13", rx: "2.5", fill: secondaryColor, opacity: secondaryOpacity }), jsxRuntime.jsx("rect", { x: "9", y: "9", width: "12", height: "12", rx: "2.5", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1", stroke: primaryColor, strokeWidth: strokeWidth })] })),
130
- vivid: ({ primaryColor, secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "9", y: "9", width: "12", height: "12", rx: "2.5", fill: primaryColor }), jsxRuntime.jsx("rect", { x: "9", y: "9", width: "12", height: "12", rx: "2.5", fill: "white", opacity: "0.1" }), jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1", stroke: secondaryColor, strokeWidth: "1.8" })] })),
146
+ solid: ({ primaryColor, strokeWidth }) => copyFilled(primaryColor, primaryColor, strokeWidth),
147
+ sharp: ({ primaryColor, strokeWidth }) => copyFilled(primaryColor, primaryColor, strokeWidth, true),
148
+ // both sheets stroked: the back line stops 1 short of the front sheet's line
149
+ outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...COPY_FRONT, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: copyBack(1 + strokeWidth), stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })] })),
150
+ duotone: ({ primaryColor, secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...COPY_BACK, fill: secondaryColor }), jsxRuntime.jsx("rect", { ...COPY_FRONT, fill: primaryColor })] })),
151
+ vivid: ({ primaryColor, secondaryColor, strokeWidth }) => copyFilled(primaryColor, secondaryColor, strokeWidth),
131
152
  },
132
153
  });
133
154
  /** NtdClipboard's two lines of text, high on the board (they sat below its middle). */
@@ -132,6 +132,8 @@ const NtdSparkle = /* @__PURE__ */ createIcon.createIcon({
132
132
  vivid: ({ primaryColor, secondaryColor: _secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2l2.4 7.2L22 12l-7.6 2.8L12 22l-2.4-7.2L2 12l7.6-2.8L12 2z", fill: primaryColor }), jsxRuntime.jsx("path", { d: "M12 2l2.4 7.2L22 12l-7.6 2.8L12 22l-2.4-7.2L2 12l7.6-2.8L12 2z", fill: "white", opacity: "0.1" })] })),
133
133
  },
134
134
  });
135
+ /** @deprecated The same four-pointed star as {@link NtdSparkle} — use that. */
136
+ const NtdStar4 = NtdSparkle;
135
137
  const NtdMagicWand = /* @__PURE__ */ createIcon.createIcon({
136
138
  displayName: 'NtdMagicWand',
137
139
  paths: {
@@ -184,6 +186,7 @@ exports.NtdNeuralNetwork = NtdNeuralNetwork;
184
186
  exports.NtdPrompt = NtdPrompt;
185
187
  exports.NtdRobot = NtdRobot;
186
188
  exports.NtdSparkle = NtdSparkle;
189
+ exports.NtdStar4 = NtdStar4;
187
190
  exports.NtdTensor = NtdTensor;
188
191
  exports.NtdTraining = NtdTraining;
189
192
  exports.NtdVoiceAssistant = NtdVoiceAssistant;
@@ -189,13 +189,21 @@ const NtdSmartphone = /* @__PURE__ */ createIcon.createIcon({
189
189
  vivid: ({ primaryColor, secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "5", y: "2", width: "14", height: "20", rx: "2", fill: primaryColor }), jsxRuntime.jsx("rect", { x: "5", y: "2", width: "14", height: "20", rx: "2", fill: "white", opacity: "0.1" }), jsxRuntime.jsx("line", { x1: "12", y1: "18", x2: "12.01", y2: "18", stroke: secondaryColor, strokeWidth: "1.8" })] })),
190
190
  },
191
191
  });
192
+ // NtdMonitor: the neck and the base are twice the stroke width in every variant but `outline`, and
193
+ // the base is 30% wider — 13 across with its caps (it was 10); it sits at 21.5 so the heavier line
194
+ // stays in the box. Vivid: the stand secondary (it had a fixed #3B82F6 neck).
195
+ const MONITOR_SCREEN = { x: 2, y: 3, width: 20, height: 14, rx: 2 };
196
+ /** Neck and base for a line twice the stroke width: base 9 long + 2 × 2 of cap = 13. */
197
+ const MONITOR_STAND = 'M12 17v4.5M7.5 21.5h9';
198
+ /** The outline's neck and base, at the stroke width: base 11 long + 2 × 1 of cap = 13. */
199
+ const MONITOR_STAND_LINE = 'M12 17v4M6.5 21h11';
192
200
  const NtdMonitor = /* @__PURE__ */ createIcon.createIcon({
193
201
  displayName: 'NtdMonitor',
194
202
  paths: {
195
- solid: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", fill: primaryColor }), jsxRuntime.jsx("line", { x1: "8", y1: "21", x2: "16", y2: "21", stroke: primaryColor, strokeWidth: strokeWidth }), jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12", y2: "21", stroke: primaryColor, strokeWidth: strokeWidth })] })),
196
- outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("line", { x1: "8", y1: "21", x2: "16", y2: "21", stroke: primaryColor, strokeWidth: strokeWidth }), jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12", y2: "21", stroke: primaryColor, strokeWidth: strokeWidth })] })),
197
- duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", fill: secondaryColor, opacity: secondaryOpacity }), jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("line", { x1: "8", y1: "21", x2: "16", y2: "21", stroke: primaryColor, strokeWidth: strokeWidth }), jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12", y2: "21", stroke: primaryColor, strokeWidth: strokeWidth })] })),
198
- vivid: ({ primaryColor, secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", fill: primaryColor }), jsxRuntime.jsx("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", fill: "white", opacity: "0.1" }), jsxRuntime.jsx("line", { x1: "8", y1: "21", x2: "16", y2: "21", stroke: secondaryColor, strokeWidth: "1.8" }), jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12", y2: "21", stroke: "#3B82F6", strokeWidth: "1.5" })] })),
203
+ solid: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...MONITOR_SCREEN, fill: primaryColor }), jsxRuntime.jsx("path", { d: MONITOR_STAND, stroke: primaryColor, strokeWidth: strokeWidth * 2 })] })),
204
+ outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...MONITOR_SCREEN, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: MONITOR_STAND_LINE, stroke: primaryColor, strokeWidth: strokeWidth })] })),
205
+ duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...MONITOR_SCREEN, fill: secondaryColor, opacity: secondaryOpacity }), jsxRuntime.jsx("rect", { ...MONITOR_SCREEN, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: MONITOR_STAND, stroke: primaryColor, strokeWidth: strokeWidth * 2 })] })),
206
+ vivid: ({ primaryColor, secondaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...MONITOR_SCREEN, fill: primaryColor }), jsxRuntime.jsx("path", { d: MONITOR_STAND, stroke: secondaryColor, strokeWidth: strokeWidth * 2 })] })),
199
207
  },
200
208
  });
201
209
  // NtdCpu: filled, the body and its pins primary and the die in the accent colour (the body was a
@@ -291,13 +299,22 @@ const NtdCreditCard = /* @__PURE__ */ createIcon.createIcon({
291
299
  vivid: ({ primaryColor, accentColor, accentOpacity, uid }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...CARD_BODY, fill: primaryColor }), jsxRuntime.jsx("rect", { ...CARD_BODY, fill: "white", opacity: "0.1" }), iconParts.within(uid, 'stripe', jsxRuntime.jsx("rect", { ...CARD_BODY }), jsxRuntime.jsx("rect", { ...CARD_STRIPE, fill: "black", opacity: "0.35" })), jsxRuntime.jsx("rect", { ...CARD_SIGNATURE, fill: accentColor, opacity: accentOpacity }), jsxRuntime.jsx("rect", { ...CARD_CVV, fill: accentColor, opacity: accentOpacity })] })),
292
300
  },
293
301
  });
302
+ // NtdPieChart: filled, two sectors of one pie (r 10) pulled 0.7 apart along the small one's
303
+ // diagonal — a gap between them. The larger is the three-quarter sector from the centre; it was a
304
+ // segment cut off by a chord, which read as an odd shape. The outline keeps its open arc and the
305
+ // slice. Duotone, fills only: the larger sector secondary, the slice primary; vivid the other way.
306
+ const PIE_REST = 'M11.3 12.7V2.7A10 10 0 1 0 21.3 12.7Z';
307
+ const PIE_SLICE = 'M12.7 11.3V1.3A10 10 0 0 1 22.7 11.3Z';
308
+ function pieFilled(rest, slice) {
309
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: PIE_REST, fill: rest }), jsxRuntime.jsx("path", { d: PIE_SLICE, fill: slice })] }));
310
+ }
294
311
  const NtdPieChart = /* @__PURE__ */ createIcon.createIcon({
295
312
  displayName: 'NtdPieChart',
296
313
  paths: {
297
- solid: ({ primaryColor, secondaryColor: _secondaryColor, secondaryOpacity: _secondaryOpacity, strokeWidth, }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M21.21 15.89A10 10 0 118 2.83", fill: primaryColor, opacity: "0.3", stroke: primaryColor, strokeWidth: strokeWidth }), jsxRuntime.jsx("path", { d: "M22 12A10 10 0 0012 2v10h10z", fill: primaryColor })] })),
314
+ solid: ({ primaryColor }) => pieFilled(primaryColor, primaryColor),
298
315
  outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M21.21 15.89A10 10 0 118 2.83", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: "M22 12A10 10 0 0012 2v10h10z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })] })),
299
- duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M21.21 15.89A10 10 0 118 2.83", fill: secondaryColor, opacity: secondaryOpacity, stroke: primaryColor, strokeWidth: strokeWidth }), jsxRuntime.jsx("path", { d: "M22 12A10 10 0 0012 2v10h10z", fill: primaryColor, stroke: primaryColor, strokeWidth: strokeWidth })] })),
300
- vivid: ({ primaryColor, secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M21.21 15.89A10 10 0 118 2.83", fill: primaryColor, opacity: "0.3", stroke: primaryColor, strokeWidth: "2" }), jsxRuntime.jsx("path", { d: "M21.21 15.89A10 10 0 118 2.83", fill: "white", opacity: "0.08" }), jsxRuntime.jsx("path", { d: "M22 12A10 10 0 0012 2v10h10z", fill: secondaryColor })] })),
316
+ duotone: ({ primaryColor, secondaryColor }) => pieFilled(secondaryColor, primaryColor),
317
+ vivid: ({ primaryColor, secondaryColor }) => pieFilled(primaryColor, secondaryColor),
301
318
  },
302
319
  });
303
320
  const NtdBarChart = /* @__PURE__ */ createIcon.createIcon({
@@ -113,7 +113,6 @@ exports.NtdCo2 = sustainability.NtdCo2;
113
113
  exports.NtdCompost = sustainability.NtdCompost;
114
114
  exports.NtdEcoFriendly = sustainability.NtdEcoFriendly;
115
115
  exports.NtdEvCharger = sustainability.NtdEvCharger;
116
- exports.NtdHydropower = sustainability.NtdHydropower;
117
116
  exports.NtdNetZero = sustainability.NtdNetZero;
118
117
  exports.NtdOrganic = sustainability.NtdOrganic;
119
118
  exports.NtdPlantTree = sustainability.NtdPlantTree;
@@ -229,6 +228,7 @@ exports.NtdDroplet = weather.NtdDroplet;
229
228
  exports.NtdFeather = weather.NtdFeather;
230
229
  exports.NtdFire = weather.NtdFire;
231
230
  exports.NtdFlower = weather.NtdFlower;
231
+ exports.NtdHydropower = weather.NtdHydropower;
232
232
  exports.NtdLeaf = weather.NtdLeaf;
233
233
  exports.NtdMountain = weather.NtdMountain;
234
234
  exports.NtdRain = weather.NtdRain;
@@ -268,7 +268,6 @@ exports.NtdRepeat = shapes.NtdRepeat;
268
268
  exports.NtdSegment = shapes.NtdSegment;
269
269
  exports.NtdShuffle = shapes.NtdShuffle;
270
270
  exports.NtdSquare = shapes.NtdSquare;
271
- exports.NtdStar4 = shapes.NtdStar4;
272
271
  exports.NtdTriangle = shapes.NtdTriangle;
273
272
  exports.NtdBank = business.NtdBank;
274
273
  exports.NtdBarcode = business.NtdBarcode;
@@ -432,6 +431,7 @@ exports.NtdNeuralNetwork = ai.NtdNeuralNetwork;
432
431
  exports.NtdPrompt = ai.NtdPrompt;
433
432
  exports.NtdRobot = ai.NtdRobot;
434
433
  exports.NtdSparkle = ai.NtdSparkle;
434
+ exports.NtdStar4 = ai.NtdStar4;
435
435
  exports.NtdTensor = ai.NtdTensor;
436
436
  exports.NtdTraining = ai.NtdTraining;
437
437
  exports.aiIcons = ai.aiIcons;
@@ -67,6 +67,8 @@ const TRIANGLE_LINE = 'M12 4.24L20.38 21H3.62Z';
67
67
  const TRIANGLE_ROUND = 'M9.76 6.47A2.5 2.5 0 0 1 14.24 6.47L20.19 18.38A2.5 2.5 0 0 1 17.95 22L6.05 22A2.5 2.5 0 0 1 3.81 18.38Z';
68
68
  const NtdTriangle = /* @__PURE__ */ createIcon.createIcon({
69
69
  displayName: 'NtdTriangle',
70
+ // text children centre on the centroid, low in the box (stacking, 1.3.5)
71
+ textCenter: [12, 15.3],
70
72
  paths: {
71
73
  solid: ({ primaryColor }) => jsxRuntime.jsx("polygon", { points: "12,2 22,22 2,22", fill: primaryColor }),
72
74
  rounded: ({ primaryColor }) => jsxRuntime.jsx("path", { d: TRIANGLE_ROUND, fill: primaryColor }),
@@ -126,15 +128,6 @@ const NtdCross = /* @__PURE__ */ createIcon.createIcon({
126
128
  rounded: ({ primaryColor }) => (jsxRuntime.jsx("path", { d: "M10.5 2h3a1.5 1.5 0 011.5 1.5V8a1 1 0 001 1h4.5a1.5 1.5 0 011.5 1.5v3a1.5 1.5 0 01-1.5 1.5H16a1 1 0 00-1 1v4.5a1.5 1.5 0 01-1.5 1.5h-3A1.5 1.5 0 019 20.5V16a1 1 0 00-1-1H3.5A1.5 1.5 0 012 13.5v-3A1.5 1.5 0 013.5 9H8a1 1 0 001-1V3.5A1.5 1.5 0 0110.5 2z", fill: primaryColor })),
127
129
  },
128
130
  });
129
- const NtdStar4 = /* @__PURE__ */ createIcon.createIcon({
130
- displayName: 'NtdStar4',
131
- paths: {
132
- solid: ({ primaryColor, strokeWidth: _strokeWidth }) => (jsxRuntime.jsx("path", { d: "M12 2l2.5 7.5L22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5z", fill: primaryColor })),
133
- outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsx("path", { d: "M12 2l2.5 7.5L22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })),
134
- duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2l2.5 7.5L22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5z", fill: secondaryColor, opacity: secondaryOpacity }), jsxRuntime.jsx("path", { d: "M12 2l2.5 7.5L22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })] })),
135
- vivid: ({ primaryColor, secondaryColor: _secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2l2.5 7.5L22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5z", fill: primaryColor }), jsxRuntime.jsx("path", { d: "M12 2l2.5 7.5L22 12l-7.5 2.5L12 22l-2.5-7.5L2 12l7.5-2.5z", fill: "white", opacity: "0.1" })] })),
136
- },
137
- });
138
131
  // The four corner arrows: the tail's level run sits at the height of the arrowhead's tip, so the
139
132
  // two meet (it ran 2 units off the tip and the head looked stuck on beside the tail). It stops 2
140
133
  // short of the tip: with the square caps of `sharp` it stuck out of the point. The filled variants
@@ -358,5 +351,4 @@ exports.NtdRepeat = NtdRepeat;
358
351
  exports.NtdSegment = NtdSegment;
359
352
  exports.NtdShuffle = NtdShuffle;
360
353
  exports.NtdSquare = NtdSquare;
361
- exports.NtdStar4 = NtdStar4;
362
354
  exports.NtdTriangle = NtdTriangle;
@@ -2,6 +2,7 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var createIcon = require('../createIcon.js');
5
+ var weather = require('./weather.js');
5
6
 
6
7
  /* ────────────────────────────────────────────────────────────────────────────
7
8
  RECYCLING & WASTE
@@ -63,15 +64,6 @@ const NtdEvCharger = /* @__PURE__ */ createIcon.createIcon({
63
64
  vivid: ({ primaryColor, secondaryColor: _secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { x: "4", y: "2", width: "12", height: "18", rx: "2", fill: primaryColor }), jsxRuntime.jsx("rect", { x: "4", y: "2", width: "12", height: "18", rx: "2", fill: "white", opacity: "0.08" }), jsxRuntime.jsx("path", { d: "M8 8h4v4H8z", fill: "white" }), jsxRuntime.jsx("circle", { cx: "10", cy: "16", r: "1", fill: "white" }), jsxRuntime.jsx("path", { d: "M10 6v2M10 12v2M8 10h4", stroke: "white", strokeWidth: "1", strokeLinecap: "round" }), jsxRuntime.jsx("path", { d: "M16 10h2a2 2 0 012 2v4a2 2 0 01-2 2h-2", stroke: "white", strokeWidth: "1", strokeLinecap: "round" })] })),
64
65
  },
65
66
  });
66
- const NtdHydropower = /* @__PURE__ */ createIcon.createIcon({
67
- displayName: 'NtdHydropower',
68
- paths: {
69
- solid: ({ primaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2c-4 4-6 7-6 10a6 6 0 1012 0c0-3-2-6-6-10z", fill: primaryColor }), jsxRuntime.jsx("path", { d: "M12 8v4l2-2M12 12l-2-2", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] })),
70
- outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2c-4 4-6 7-6 10a6 6 0 1012 0c0-3-2-6-6-10z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: "M12 8v4l2-2M12 12l-2-2", stroke: primaryColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })] })),
71
- duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2c-4 4-6 7-6 10a6 6 0 1012 0c0-3-2-6-6-10z", fill: secondaryColor, opacity: secondaryOpacity }), jsxRuntime.jsx("path", { d: "M12 2c-4 4-6 7-6 10a6 6 0 1012 0c0-3-2-6-6-10z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: "M12 8v4l2-2M12 12l-2-2", stroke: primaryColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })] })),
72
- vivid: ({ primaryColor, secondaryColor: _secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2c-4 4-6 7-6 10a6 6 0 1012 0c0-3-2-6-6-10z", fill: primaryColor }), jsxRuntime.jsx("path", { d: "M12 2c-4 4-6 7-6 10a6 6 0 1012 0c0-3-2-6-6-10z", fill: "white", opacity: "0.1" }), jsxRuntime.jsx("path", { d: "M12 8v4l2-2M12 12l-2-2", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" })] })),
73
- },
74
- });
75
67
  /* ────────────────────────────────────────────────────────────────────────────
76
68
  CARBON & CLIMATE
77
69
  ───────────────────────────────────────────────────────────────────────────── */
@@ -163,7 +155,7 @@ const sustainabilityIcons = {
163
155
  NtdSolarPanel,
164
156
  NtdWindTurbine,
165
157
  NtdEvCharger,
166
- NtdHydropower,
158
+ NtdHydropower: weather.NtdHydropower,
167
159
  NtdCarbonFootprint,
168
160
  NtdCo2,
169
161
  NtdNetZero,
@@ -180,7 +172,6 @@ exports.NtdCo2 = NtdCo2;
180
172
  exports.NtdCompost = NtdCompost;
181
173
  exports.NtdEcoFriendly = NtdEcoFriendly;
182
174
  exports.NtdEvCharger = NtdEvCharger;
183
- exports.NtdHydropower = NtdHydropower;
184
175
  exports.NtdNetZero = NtdNetZero;
185
176
  exports.NtdOrganic = NtdOrganic;
186
177
  exports.NtdPlantTree = NtdPlantTree;
@@ -64,6 +64,8 @@ const NtdUsers = /* @__PURE__ */ createIcon.createIcon({
64
64
  const HEART = 'M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z';
65
65
  const NtdHeart = /* @__PURE__ */ createIcon.createIcon({
66
66
  displayName: 'NtdHeart',
67
+ // text children centre on the middle of the lobes and the point (stacking, 1.3.5)
68
+ textCenter: [12, 11.2],
67
69
  paths: {
68
70
  solid: ({ primaryColor, strokeWidth: _strokeWidth }) => (jsxRuntime.jsx("path", { d: "M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z", fill: primaryColor })),
69
71
  outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsx("path", { d: "M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })),
@@ -73,6 +75,8 @@ const NtdHeart = /* @__PURE__ */ createIcon.createIcon({
73
75
  });
74
76
  const NtdStar = /* @__PURE__ */ createIcon.createIcon({
75
77
  displayName: 'NtdStar',
78
+ // text children centre on the middle of the body, below the box centre (stacking, 1.3.5)
79
+ textCenter: [12, 12.6],
76
80
  paths: {
77
81
  solid: ({ primaryColor, strokeWidth: _strokeWidth }) => (jsxRuntime.jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z", fill: primaryColor })),
78
82
  outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })),
@@ -276,6 +280,8 @@ const NtdThumbDown = /* @__PURE__ */ createIcon.createIcon({
276
280
  });
277
281
  const NtdShield = /* @__PURE__ */ createIcon.createIcon({
278
282
  displayName: 'NtdShield',
283
+ // text children centre on the wide upper part of the shield (stacking, 1.3.5)
284
+ textCenter: [12, 11],
279
285
  paths: {
280
286
  solid: ({ primaryColor, strokeWidth: _strokeWidth }) => (jsxRuntime.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z", fill: primaryColor })),
281
287
  outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z", stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })),
@@ -74,6 +74,8 @@ const NtdDroplet = /* @__PURE__ */ createIcon.createIcon({
74
74
  vivid: ({ primaryColor, secondaryColor: _secondaryColor }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M12 2.5C13.1 6.2 17.6 9.4 17.6 14.4a5.6 6.2 0 1 1-11.2 0C6.4 9.4 10.9 6.2 12 2.5z", fill: primaryColor }), jsxRuntime.jsx("path", { d: "M12 2.5C13.1 6.2 17.6 9.4 17.6 14.4a5.6 6.2 0 1 1-11.2 0C6.4 9.4 10.9 6.2 12 2.5z", fill: "white", opacity: "0.1" })] })),
75
75
  },
76
76
  });
77
+ /** @deprecated The same drop as {@link NtdDroplet} — use that. */
78
+ const NtdHydropower = NtdDroplet;
77
79
  const NtdThermometer = /* @__PURE__ */ createIcon.createIcon({
78
80
  displayName: 'NtdThermometer',
79
81
  paths: {
@@ -215,6 +217,7 @@ exports.NtdDroplet = NtdDroplet;
215
217
  exports.NtdFeather = NtdFeather;
216
218
  exports.NtdFire = NtdFire;
217
219
  exports.NtdFlower = NtdFlower;
220
+ exports.NtdHydropower = NtdHydropower;
218
221
  exports.NtdLeaf = NtdLeaf;
219
222
  exports.NtdMountain = NtdMountain;
220
223
  exports.NtdRain = NtdRain;
package/dist/cjs/index.js CHANGED
@@ -4,6 +4,7 @@ var types = require('./types.js');
4
4
  var createIcon = require('./createIcon.js');
5
5
  var smilAnimations = require('./smilAnimations.js');
6
6
  var NiceIconPicker = require('./NiceIconPicker.js');
7
+ var NiceIconStacker = require('./NiceIconStacker.js');
7
8
  var animationControls = require('./animationControls.js');
8
9
  var figmaExport = require('./figmaExport.js');
9
10
  var navigation = require('./icons/navigation.js');
@@ -68,6 +69,8 @@ exports.createSmilAnimationDef = smilAnimations.createSmilAnimationDef;
68
69
  exports.generateSmilAnimation = smilAnimations.generateSmilAnimation;
69
70
  exports.isSmilSupported = smilAnimations.isSmilSupported;
70
71
  exports.NiceIconPicker = NiceIconPicker.NiceIconPicker;
72
+ exports.NiceIconStacker = NiceIconStacker.NiceIconStacker;
73
+ exports.niceIconStackCode = NiceIconStacker.niceIconStackCode;
71
74
  exports.AnimationController = animationControls.AnimationController;
72
75
  exports.InteractiveIcon = animationControls.InteractiveIcon;
73
76
  exports.NiceAnimationController = animationControls.AnimationController;
@@ -167,7 +170,6 @@ exports.NtdCo2 = sustainability.NtdCo2;
167
170
  exports.NtdCompost = sustainability.NtdCompost;
168
171
  exports.NtdEcoFriendly = sustainability.NtdEcoFriendly;
169
172
  exports.NtdEvCharger = sustainability.NtdEvCharger;
170
- exports.NtdHydropower = sustainability.NtdHydropower;
171
173
  exports.NtdNetZero = sustainability.NtdNetZero;
172
174
  exports.NtdOrganic = sustainability.NtdOrganic;
173
175
  exports.NtdPlantTree = sustainability.NtdPlantTree;
@@ -283,6 +285,7 @@ exports.NtdDroplet = weather.NtdDroplet;
283
285
  exports.NtdFeather = weather.NtdFeather;
284
286
  exports.NtdFire = weather.NtdFire;
285
287
  exports.NtdFlower = weather.NtdFlower;
288
+ exports.NtdHydropower = weather.NtdHydropower;
286
289
  exports.NtdLeaf = weather.NtdLeaf;
287
290
  exports.NtdMountain = weather.NtdMountain;
288
291
  exports.NtdRain = weather.NtdRain;
@@ -322,7 +325,6 @@ exports.NtdRepeat = shapes.NtdRepeat;
322
325
  exports.NtdSegment = shapes.NtdSegment;
323
326
  exports.NtdShuffle = shapes.NtdShuffle;
324
327
  exports.NtdSquare = shapes.NtdSquare;
325
- exports.NtdStar4 = shapes.NtdStar4;
326
328
  exports.NtdTriangle = shapes.NtdTriangle;
327
329
  exports.NtdBank = business.NtdBank;
328
330
  exports.NtdBarcode = business.NtdBarcode;
@@ -486,6 +488,7 @@ exports.NtdNeuralNetwork = ai.NtdNeuralNetwork;
486
488
  exports.NtdPrompt = ai.NtdPrompt;
487
489
  exports.NtdRobot = ai.NtdRobot;
488
490
  exports.NtdSparkle = ai.NtdSparkle;
491
+ exports.NtdStar4 = ai.NtdStar4;
489
492
  exports.NtdTensor = ai.NtdTensor;
490
493
  exports.NtdTraining = ai.NtdTraining;
491
494
  exports.aiIcons = ai.aiIcons;