@nice2dev/icons 1.3.4 → 1.3.6
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 +70 -0
- package/README.md +48 -0
- package/dist/cjs/NiceIconStacker.js +184 -0
- package/dist/cjs/client.js +7 -0
- package/dist/cjs/createIcon.js +21 -3
- package/dist/cjs/iconStack.js +111 -0
- package/dist/cjs/icons/actions.js +25 -4
- package/dist/cjs/icons/ai.js +3 -0
- package/dist/cjs/icons/files.js +24 -7
- package/dist/cjs/icons/index.js +2 -2
- package/dist/cjs/icons/shapes.js +2 -10
- package/dist/cjs/icons/sustainability.js +2 -11
- package/dist/cjs/icons/ui.js +6 -0
- package/dist/cjs/icons/weather.js +3 -0
- package/dist/cjs/index.js +9 -2
- package/dist/cjs/nicetodev-icons.css +1 -1
- package/dist/cjs/stacking.js +117 -0
- package/dist/esm/NiceIconStacker.js +181 -0
- package/dist/esm/client.js +2 -0
- package/dist/esm/createIcon.js +23 -5
- package/dist/esm/iconParts.js +1 -1
- package/dist/esm/iconStack.js +104 -0
- package/dist/esm/icons/actions.js +25 -4
- package/dist/esm/icons/ai.js +3 -1
- package/dist/esm/icons/business.js +1 -1
- package/dist/esm/icons/files.js +26 -9
- package/dist/esm/icons/index.js +4 -4
- package/dist/esm/icons/media.js +1 -1
- package/dist/esm/icons/shapes.js +3 -10
- package/dist/esm/icons/sustainability.js +2 -10
- package/dist/esm/icons/ui.js +6 -0
- package/dist/esm/icons/weather.js +3 -1
- package/dist/esm/index.js +6 -4
- package/dist/esm/nicetodev-icons.css +1 -1
- package/dist/esm/smilAnimations.js +1 -1
- package/dist/esm/stacking.js +108 -0
- package/dist/types/NiceIconStacker.d.ts +40 -0
- package/dist/types/client.d.ts +4 -0
- package/dist/types/createIcon.d.ts +5 -0
- package/dist/types/iconStack.d.ts +77 -0
- package/dist/types/icons/ai.d.ts +2 -0
- package/dist/types/icons/index.d.ts +4 -4
- package/dist/types/icons/shapes.d.ts +0 -1
- package/dist/types/icons/sustainability.d.ts +0 -1
- package/dist/types/icons/weather.d.ts +2 -0
- package/dist/types/index.d.ts +5 -1
- package/dist/types/stacking.d.ts +49 -0
- package/dist/types/types.d.ts +32 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# @nice2dev/icons — Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4bdd01c: NiceIconStacker builds stacks nested any number of levels deep:
|
|
8
|
+
|
|
9
|
+
- **Nesting:** a layer sits in its `parent` (a new optional field). A layer without one sits in
|
|
10
|
+
the base, as in 1.3.5.
|
|
11
|
+
- **Where icons go:** "Add" puts the current icon into the selected layer and then selects it, so
|
|
12
|
+
adding again nests one level deeper (`<NtdBitcoin><NtdStar><NtdSparkle>1</NtdSparkle></NtdStar></NtdBitcoin>`).
|
|
13
|
+
Select an outer layer to put icons side by side.
|
|
14
|
+
- **Display:**
|
|
15
|
+
- layers are indented by depth;
|
|
16
|
+
- text is the innermost level, offered under the deepest icons;
|
|
17
|
+
- the colours flip at every level.
|
|
18
|
+
- **Removing:** removing a layer moves what sat in it up into its parent.
|
|
19
|
+
- **Handle:** a ref handle (`NiceIconStackerHandle`: `add`, `clear`) lets a parent run "add" from a
|
|
20
|
+
button of its own.
|
|
21
|
+
- **Translations:** new keys `iconStacker.addInto` and `iconStacker.target`.
|
|
22
|
+
- **Smaller text:** the default size of stacked text is three quarters of the 1.3.5 size (9, 7.5,
|
|
23
|
+
6, 5 by length).
|
|
24
|
+
- **`stackRotation`:** turns a stacked icon about its own centre.
|
|
25
|
+
- **NiceIconStacker:** every layer can turn and take its own primary, secondary and accent colours
|
|
26
|
+
(with "auto" to follow its parent), and its text a size and colour of its own.
|
|
27
|
+
- **Bound text:**
|
|
28
|
+
- in the stacker, text can be bound to a value ("Bind to"): the code writes `{count}`, and the
|
|
29
|
+
text stays a sample;
|
|
30
|
+
- the new `NiceIconStack` draws a stack kept as data with live values (`values={{ count }}`).
|
|
31
|
+
- **`renderIconStack`** draws a stack as one icon tree.
|
|
32
|
+
- **`half-` positions:** `stackAlign` takes every position again with `half-` (`half-top`,
|
|
33
|
+
`half-top-right`, `half-bottom`, …). The icon sits halfway between the centre and that edge or
|
|
34
|
+
corner, inside the parent, so it is cut out like centred content (only full corners are
|
|
35
|
+
badges).
|
|
36
|
+
|
|
37
|
+
## 1.3.5
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- 2b49cd7: Icon browser feedback, round 36:
|
|
42
|
+
|
|
43
|
+
- `NtdMonitor`: neck and base twice the stroke width in every variant but `outline`; the base
|
|
44
|
+
30% wider. Vivid's stand is secondary (it had a fixed `#3B82F6`).
|
|
45
|
+
- `NtdPieChart`: the larger part is a proper three-quarter sector from the centre (it was a segment
|
|
46
|
+
cut off by a chord). The two sectors have a gap between them; duotone uses fills only.
|
|
47
|
+
- `NtdCopy`:
|
|
48
|
+
- the front, filled sheet at the top right;
|
|
49
|
+
- the back sheet's line stops 1 short of it at any stroke width;
|
|
50
|
+
- `sharp` draws the back sheet with square corners;
|
|
51
|
+
- duotone uses fills only.
|
|
52
|
+
- `NtdStar4` is now a deprecated alias of `NtdSparkle`, and `NtdHydropower` of `NtdDroplet`. Both
|
|
53
|
+
are duplicates; the old names still work.
|
|
54
|
+
|
|
55
|
+
- 16d420b: Stack icons by nesting them, and build stacks in NiceIconStacker:
|
|
56
|
+
|
|
57
|
+
- An icon draws its children in its own SVG:
|
|
58
|
+
`<NtdSquare><NtdStar stackAlign="center">1</NtdStar></NtdSquare>`.
|
|
59
|
+
- **Child icons** sit where `stackAlign` says: `center`, an edge or a corner. `stackSize` sets
|
|
60
|
+
their share of the parent (default 0.6 centred, 0.5 elsewhere).
|
|
61
|
+
- **Text children** are centred on the icon's visual centre. `NtdStar`, `NtdHeart`, `NtdShield`
|
|
62
|
+
and `NtdTriangle` have their own centre (`textCenter` in `createIcon`). `textColor` and
|
|
63
|
+
`textSize` override the text's colour and size.
|
|
64
|
+
- **Colours** follow the parent: a filled parent cuts centred and edge content out (the parent's
|
|
65
|
+
accent); a corner badge keeps the parent's colours on an accent-coloured gap. Colours given on
|
|
66
|
+
a child win.
|
|
67
|
+
- `NiceIconStacker`:
|
|
68
|
+
- lists the base icon and the icons stacked in it, each with its position, size and text;
|
|
69
|
+
- adds the `current` icon, removes one or clears the stack;
|
|
70
|
+
- previews the stack at three sizes and writes its JSX (`niceIconStackCode`).
|
|
71
|
+
- New translation keys `iconStacker.*` (en, pl, de, fr, es, uk).
|
|
72
|
+
|
|
3
73
|
## 1.3.4
|
|
4
74
|
|
|
5
75
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -205,6 +205,54 @@ 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
|
+
<NtdBitcoin>
|
|
225
|
+
<NtdStar>
|
|
226
|
+
<NtdSparkle>1</NtdSparkle>
|
|
227
|
+
</NtdStar>
|
|
228
|
+
</NtdBitcoin>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Stacks nest any number of levels deep, with the colours flipping at every level.
|
|
232
|
+
|
|
233
|
+
- **`stackAlign`:** `center` (default), `top`, `bottom`, `left`, `right`, `top-left`,
|
|
234
|
+
`top-right`, `bottom-left`, `bottom-right`, plus each of them with `half-` (`half-top`,
|
|
235
|
+
`half-bottom-right`, …), halfway from the centre to that edge or corner.
|
|
236
|
+
- **`stackSize`:** the child's share of its parent. Default `0.6` centred, `0.5` elsewhere.
|
|
237
|
+
- **Colours** follow the parent unless the child sets its own:
|
|
238
|
+
- In the centre or at an edge, a filled parent cuts the content out. The child takes the
|
|
239
|
+
parent's accent and its text the parent's primary. On `outline` / `wireframe` everything stays
|
|
240
|
+
in primary.
|
|
241
|
+
- A corner badge keeps the parent's colours and sits on an accent-coloured gap.
|
|
242
|
+
- **`stackRotation`:** turns a stacked icon about its own centre, in degrees clockwise. Its
|
|
243
|
+
contents and text turn with it.
|
|
244
|
+
- **Text:** the default size is 9, 7.5, 6 or 5 in the 24-unit box (by length). `textColor` and
|
|
245
|
+
`textSize` override the text's colour and size.
|
|
246
|
+
- **Data:** `NiceIconStack` draws a stack kept as data (NiceIconStacker's layers), its bound text
|
|
247
|
+
filled from `values`. This works with live numbers, for example
|
|
248
|
+
`<NiceIconStack layers={stack} icons={icons} values={{ count }} />`.
|
|
249
|
+
- **Builder:** `NiceIconStacker` builds a stack interactively and writes the JSX
|
|
250
|
+
(`niceIconStackCode`). Each icon you add goes into the selected layer, which is the newest one,
|
|
251
|
+
so adding nests deeper. Select an outer layer to put icons side by side. Text is the innermost
|
|
252
|
+
level.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
208
256
|
### Gradient Fills
|
|
209
257
|
|
|
210
258
|
Apply gradient fills using the `gradient` prop with one of 12 built-in presets:
|
|
@@ -0,0 +1,184 @@
|
|
|
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 navigation = require('./icons/navigation.js');
|
|
8
|
+
var iconStack = require('./iconStack.js');
|
|
9
|
+
var stacking = require('./stacking.js');
|
|
10
|
+
|
|
11
|
+
const ALIGNS = [
|
|
12
|
+
'center',
|
|
13
|
+
'top',
|
|
14
|
+
'bottom',
|
|
15
|
+
'left',
|
|
16
|
+
'right',
|
|
17
|
+
'top-left',
|
|
18
|
+
'top-right',
|
|
19
|
+
'bottom-left',
|
|
20
|
+
'bottom-right',
|
|
21
|
+
'half-top',
|
|
22
|
+
'half-bottom',
|
|
23
|
+
'half-left',
|
|
24
|
+
'half-right',
|
|
25
|
+
'half-top-left',
|
|
26
|
+
'half-top-right',
|
|
27
|
+
'half-bottom-left',
|
|
28
|
+
'half-bottom-right',
|
|
29
|
+
];
|
|
30
|
+
const PREVIEW_SIZES = [96, 48, 24];
|
|
31
|
+
const NO_LAYERS = [];
|
|
32
|
+
/** What a colour field shows while the colour is unset (follows the parent). */
|
|
33
|
+
const AUTO_SWATCH = '#808080';
|
|
34
|
+
/** The layers in tree order (each followed by what sits in it), with their depth. */
|
|
35
|
+
function walk(layers) {
|
|
36
|
+
const out = [];
|
|
37
|
+
const visit = (layer, depth) => {
|
|
38
|
+
out.push({ layer, depth });
|
|
39
|
+
for (const child of iconStack.stackChildrenOf(layers, layer.id)) {
|
|
40
|
+
visit(child, depth + 1);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
if (layers[0]) {
|
|
44
|
+
visit(layers[0], 0);
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
/** Removes a layer; what sat in it moves up into its parent (a removed base hands over to its first child). */
|
|
49
|
+
function removeLayer(layers, id) {
|
|
50
|
+
const base = layers[0];
|
|
51
|
+
if (!base) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
if (id !== base.id) {
|
|
55
|
+
const gone = layers.find((l) => l.id === id);
|
|
56
|
+
const up = gone ? iconStack.stackParentId(layers, gone) : undefined;
|
|
57
|
+
return layers
|
|
58
|
+
.filter((l) => l.id !== id)
|
|
59
|
+
.map((l) => (l.parent === id ? { ...l, parent: up === base.id ? undefined : up } : l));
|
|
60
|
+
}
|
|
61
|
+
const [heir, ...siblings] = iconStack.stackChildrenOf(layers, base.id);
|
|
62
|
+
if (!heir) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const newBase = {
|
|
66
|
+
...heir,
|
|
67
|
+
parent: undefined,
|
|
68
|
+
align: undefined,
|
|
69
|
+
size: undefined,
|
|
70
|
+
rotation: undefined,
|
|
71
|
+
};
|
|
72
|
+
return [
|
|
73
|
+
newBase,
|
|
74
|
+
...layers
|
|
75
|
+
.filter((l) => l.id !== base.id && l.id !== heir.id)
|
|
76
|
+
.map((l) => siblings.includes(l)
|
|
77
|
+
? { ...l, parent: heir.id }
|
|
78
|
+
: l.parent === heir.id
|
|
79
|
+
? { ...l, parent: undefined }
|
|
80
|
+
: l),
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
/** A colour of the layer's own, or "auto" — following its parent — until one is picked. */
|
|
84
|
+
function ColorField({ label, value, onChange, autoLabel, resetLabel }) {
|
|
85
|
+
return (jsxRuntime.jsxs("span", { className: "nice-icon-stacker__color", children: [jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: label }), jsxRuntime.jsx("input", { type: "color", value: value !== null && value !== void 0 ? value : AUTO_SWATCH, onChange: (e) => onChange(e.target.value) })] }), value ? (jsxRuntime.jsx("button", { type: "button", className: "nice-icon-stacker__reset", onClick: () => onChange(undefined), "aria-label": resetLabel, title: resetLabel, children: jsxRuntime.jsx(navigation.NtdClose, { size: 12 }) })) : (jsxRuntime.jsx("small", { className: "nice-icon-stacker__auto", children: autoLabel }))] }));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* NiceIconStacker (1.3.5) — builds an icon stack: the base icon and the icons stacked in it, each
|
|
89
|
+
* with its position, size, turn and colours, nested any number of levels deep (1.3.6) with text
|
|
90
|
+
* innermost — its size, colour and the value it is bound to — shown live at three sizes and as the
|
|
91
|
+
* JSX that draws it. The "add" button puts `current` into the selected layer and selects it, so
|
|
92
|
+
* adding again goes one level deeper; select an outer layer to add side by side. Layers leave one
|
|
93
|
+
* by one or all at once. `NiceIconStack` draws a stack built here from data.
|
|
94
|
+
*/
|
|
95
|
+
const NiceIconStacker = React.forwardRef(function NiceIconStacker({ icons, layers: layersProp, defaultLayers, onLayersChange, current, previewProps, className }, ref) {
|
|
96
|
+
var _a, _b, _c, _d;
|
|
97
|
+
const { t } = uiCore.useNiceTranslation();
|
|
98
|
+
const [layers, setLayers] = uiCore.useControllableState({
|
|
99
|
+
value: layersProp,
|
|
100
|
+
defaultValue: defaultLayers,
|
|
101
|
+
fallbackValue: NO_LAYERS,
|
|
102
|
+
onChange: onLayersChange,
|
|
103
|
+
componentName: 'NiceIconStacker',
|
|
104
|
+
});
|
|
105
|
+
const nextId = React.useRef(0);
|
|
106
|
+
const targetGroup = React.useId();
|
|
107
|
+
const [copied, setCopied] = React.useState(false);
|
|
108
|
+
// The layer the next icon goes into — the newest by default, so adding nests deeper.
|
|
109
|
+
const [selected, setSelected] = React.useState(undefined);
|
|
110
|
+
const base = layers[0];
|
|
111
|
+
const target = (_b = (_a = layers.find((l) => l.id === selected)) !== null && _a !== void 0 ? _a : layers[layers.length - 1]) !== null && _b !== void 0 ? _b : undefined;
|
|
112
|
+
const resolve = React.useCallback((name) => (typeof icons === 'function' ? icons(name) : icons[name]), [icons]);
|
|
113
|
+
const tree = React.useMemo(() => walk(layers), [layers]);
|
|
114
|
+
const code = React.useMemo(() => iconStack.niceIconStackCode(layers), [layers]);
|
|
115
|
+
const update = (id, patch) => setLayers((prev) => prev.map((l) => (l.id === id ? { ...l, ...patch } : l)));
|
|
116
|
+
const add = () => {
|
|
117
|
+
if (!current) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
nextId.current += 1;
|
|
121
|
+
const id = `${current.icon}-${Date.now().toString(36)}-${nextId.current}`;
|
|
122
|
+
setLayers((prev) => {
|
|
123
|
+
const into = prev.find((l) => l.id === (target === null || target === void 0 ? void 0 : target.id));
|
|
124
|
+
const layer = {
|
|
125
|
+
id,
|
|
126
|
+
icon: current.icon,
|
|
127
|
+
variant: current.variant,
|
|
128
|
+
...(into && into !== prev[0] ? { parent: into.id } : {}),
|
|
129
|
+
};
|
|
130
|
+
return [...prev, layer];
|
|
131
|
+
});
|
|
132
|
+
setSelected(id);
|
|
133
|
+
};
|
|
134
|
+
const remove = (id) => {
|
|
135
|
+
setLayers((prev) => removeLayer(prev, id));
|
|
136
|
+
if (selected === id) {
|
|
137
|
+
setSelected(undefined);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const clear = () => {
|
|
141
|
+
setLayers(NO_LAYERS);
|
|
142
|
+
setSelected(undefined);
|
|
143
|
+
};
|
|
144
|
+
React.useImperativeHandle(ref, () => ({ add, clear }));
|
|
145
|
+
const copy = () => {
|
|
146
|
+
var _a;
|
|
147
|
+
void ((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText(code).then(() => {
|
|
148
|
+
setCopied(true);
|
|
149
|
+
window.setTimeout(() => setCopied(false), 1500);
|
|
150
|
+
}));
|
|
151
|
+
};
|
|
152
|
+
const autoLabel = t('iconStacker.auto', 'auto');
|
|
153
|
+
const resetLabel = t('iconStacker.reset', 'Back to auto');
|
|
154
|
+
const addLabel = base && target
|
|
155
|
+
? t('iconStacker.addInto', 'Add {icon} into {target}')
|
|
156
|
+
.replace('{icon}', (_c = current === null || current === void 0 ? void 0 : current.icon) !== null && _c !== void 0 ? _c : '')
|
|
157
|
+
.replace('{target}', target.icon)
|
|
158
|
+
: t('iconStacker.add', 'Add {icon} to the stack').replace('{icon}', (_d = current === null || current === void 0 ? void 0 : current.icon) !== null && _d !== void 0 ? _d : '');
|
|
159
|
+
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 }), " ", addLabel] }), jsxRuntime.jsxs("button", { type: "button", onClick: clear, disabled: layers.length === 0, children: [jsxRuntime.jsx(actions.NtdTrash, { size: 14 }), " ", t('iconStacker.clear', 'Clear the stack')] })] }), !base ? (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: [iconStack.renderIconStack(layers, icons, {
|
|
160
|
+
baseProps: { ...previewProps, size: s, title: base.icon },
|
|
161
|
+
}), jsxRuntime.jsxs("small", { children: [s, "px"] })] }, s))) }), jsxRuntime.jsx("ol", { className: "nice-icon-stacker__layers", "aria-label": t('iconStacker.layers', 'Layers'), children: tree.map(({ layer: l, depth }) => {
|
|
162
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
163
|
+
const Icon = resolve(l.icon);
|
|
164
|
+
const isBase = l === base;
|
|
165
|
+
const align = (_a = l.align) !== null && _a !== void 0 ? _a : 'center';
|
|
166
|
+
const share = (_b = l.size) !== null && _b !== void 0 ? _b : stacking.defaultStackSize(align);
|
|
167
|
+
const innermost = iconStack.stackChildrenOf(layers, l.id).length === 0;
|
|
168
|
+
const textSize = (_c = l.textSize) !== null && _c !== void 0 ? _c : stacking.defaultTextSize(((_d = l.text) !== null && _d !== void 0 ? _d : '').length || 1);
|
|
169
|
+
const bindingInvalid = !!l.textBinding && !iconStack.isValidTextBinding(l.textBinding);
|
|
170
|
+
const depthStyle = {
|
|
171
|
+
['--nice-icon-stacker-depth']: String(depth),
|
|
172
|
+
};
|
|
173
|
+
const label = (key, fallback) => t(key, fallback).replace('{icon}', l.icon);
|
|
174
|
+
return (jsxRuntime.jsxs("li", { className: "nice-icon-stacker__layer", style: depthStyle, children: [jsxRuntime.jsxs("div", { className: "nice-icon-stacker__layer-row", children: [jsxRuntime.jsx("input", { type: "radio", name: targetGroup, checked: (target === null || target === void 0 ? void 0 : target.id) === l.id, onChange: () => setSelected(l.id), "aria-label": label('iconStacker.target', 'Add the next icon into {icon}'), title: label('iconStacker.target', 'Add the next icon into {icon}') }), 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.jsx("button", { type: "button", className: "nice-icon-stacker__remove", onClick: () => remove(l.id), "aria-label": label('iconStacker.remove', 'Remove {icon}'), title: label('iconStacker.remove', 'Remove {icon}'), children: jsxRuntime.jsx(actions.NtdTrash, { size: 14 }) })] }), jsxRuntime.jsxs("details", { className: "nice-icon-stacker__more", children: [jsxRuntime.jsx("summary", { children: t('iconStacker.more', 'More') }), jsxRuntime.jsxs("div", { className: "nice-icon-stacker__more-body", children: [!isBase && (jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.rotation', 'Turn') }), jsxRuntime.jsx("input", { type: "range", min: -180, max: 180, step: 15, value: (_e = l.rotation) !== null && _e !== void 0 ? _e : 0, onChange: (e) => update(l.id, { rotation: Number(e.target.value) || undefined }) }), jsxRuntime.jsxs("output", { children: [(_f = l.rotation) !== null && _f !== void 0 ? _f : 0, "\u00B0"] })] })), jsxRuntime.jsx(ColorField, { label: t('iconStacker.primary', 'Primary'), value: l.primaryColor, onChange: (v) => update(l.id, { primaryColor: v }), autoLabel: autoLabel, resetLabel: resetLabel }), jsxRuntime.jsx(ColorField, { label: t('iconStacker.secondary', 'Secondary'), value: l.secondaryColor, onChange: (v) => update(l.id, { secondaryColor: v }), autoLabel: autoLabel, resetLabel: resetLabel }), jsxRuntime.jsx(ColorField, { label: t('iconStacker.accent', 'Accent'), value: l.accentColor, onChange: (v) => update(l.id, { accentColor: v }), autoLabel: autoLabel, resetLabel: resetLabel })] })] }), (innermost || l.text || l.textBinding) && (jsxRuntime.jsxs("div", { className: "nice-icon-stacker__text", children: [jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.text', 'Text') }), jsxRuntime.jsx("input", { type: "text", value: (_g = l.text) !== null && _g !== void 0 ? _g : '', maxLength: 4, onChange: (e) => update(l.id, { text: e.target.value || undefined }) })] }), jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.textSize', 'Text size') }), jsxRuntime.jsx("input", { type: "range", min: 3, max: 14, step: 0.5, value: textSize, onChange: (e) => update(l.id, { textSize: Number(e.target.value) }) }), jsxRuntime.jsx("output", { children: textSize }), l.textSize !== undefined && (jsxRuntime.jsx("button", { type: "button", className: "nice-icon-stacker__reset", onClick: () => update(l.id, { textSize: undefined }), "aria-label": resetLabel, title: resetLabel, children: jsxRuntime.jsx(navigation.NtdClose, { size: 12 }) }))] }), jsxRuntime.jsx(ColorField, { label: t('iconStacker.textColor', 'Text colour'), value: l.textColor, onChange: (v) => update(l.id, { textColor: v }), autoLabel: autoLabel, resetLabel: resetLabel }), jsxRuntime.jsxs("label", { className: "nice-icon-stacker__field", children: [jsxRuntime.jsx("span", { children: t('iconStacker.bind', 'Bind to') }), jsxRuntime.jsx("input", { type: "text", value: (_h = l.textBinding) !== null && _h !== void 0 ? _h : '', "aria-invalid": bindingInvalid || undefined, title: t('iconStacker.bindHint', 'The name of the value the text shows, e.g. count — the text above is a sample'), onChange: (e) => update(l.id, { textBinding: e.target.value.trim() || undefined }) })] })] }))] }, l.id));
|
|
175
|
+
}) }), 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
|
|
176
|
+
? t('iconStacker.copied', 'Copied')
|
|
177
|
+
: t('iconStacker.copy', 'Copy the code')] })] })] }))] }));
|
|
178
|
+
});
|
|
179
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
180
|
+
NiceIconStacker.displayName = 'NiceIconStacker';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
exports.niceIconStackCode = iconStack.niceIconStackCode;
|
|
184
|
+
exports.NiceIconStacker = NiceIconStacker;
|
package/dist/cjs/client.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var animationControls = require('./animationControls.js');
|
|
4
4
|
var NiceIconPicker = require('./NiceIconPicker.js');
|
|
5
|
+
var NiceIconStacker = require('./NiceIconStacker.js');
|
|
6
|
+
var iconStack = require('./iconStack.js');
|
|
5
7
|
var NtdIconMorph = require('./NtdIconMorph.js');
|
|
6
8
|
var NtdIconBadge = require('./NtdIconBadge.js');
|
|
7
9
|
var smilAnimations = require('./smilAnimations.js');
|
|
@@ -18,6 +20,11 @@ exports.createHoverAnimation = animationControls.createHoverAnimation;
|
|
|
18
20
|
exports.createVisibilityAnimation = animationControls.createVisibilityAnimation;
|
|
19
21
|
exports.useAnimationSequence = animationControls.useAnimationSequence;
|
|
20
22
|
exports.NiceIconPicker = NiceIconPicker.NiceIconPicker;
|
|
23
|
+
exports.NiceIconStacker = NiceIconStacker.NiceIconStacker;
|
|
24
|
+
exports.NiceIconStack = iconStack.NiceIconStack;
|
|
25
|
+
exports.isValidTextBinding = iconStack.isValidTextBinding;
|
|
26
|
+
exports.niceIconStackCode = iconStack.niceIconStackCode;
|
|
27
|
+
exports.renderIconStack = iconStack.renderIconStack;
|
|
21
28
|
exports.NtdIconMorph = NtdIconMorph.NtdIconMorph;
|
|
22
29
|
exports.NtdMorphPair = NtdIconMorph.NtdMorphPair;
|
|
23
30
|
exports.NtdPathMorph = NtdIconMorph.NtdPathMorph;
|
package/dist/cjs/createIcon.js
CHANGED
|
@@ -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',
|
|
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, stackRotation: _stackRotation, 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
|
-
|
|
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
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
|
|
6
|
+
/** A name `textBinding` can take: a JavaScript identifier. */
|
|
7
|
+
function isValidTextBinding(name) {
|
|
8
|
+
return !!name && /^[A-Za-z_$][\w$]*$/.test(name);
|
|
9
|
+
}
|
|
10
|
+
/** The id of the layer `layer` sits in, `undefined` for the base. */
|
|
11
|
+
function stackParentId(layers, layer) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
return layer === layers[0] ? undefined : ((_a = layer.parent) !== null && _a !== void 0 ? _a : (_b = layers[0]) === null || _b === void 0 ? void 0 : _b.id);
|
|
14
|
+
}
|
|
15
|
+
/** The layers that sit directly in layer `id`, in order. */
|
|
16
|
+
function stackChildrenOf(layers, id) {
|
|
17
|
+
return layers.filter((l) => l !== layers[0] && stackParentId(layers, l) === id);
|
|
18
|
+
}
|
|
19
|
+
const COLOR_PROPS = ['primaryColor', 'secondaryColor', 'accentColor', 'textColor'];
|
|
20
|
+
/** The stack as JSX: every layer wrapping the layers that sit in it, text innermost. */
|
|
21
|
+
function niceIconStackCode(layers) {
|
|
22
|
+
const base = layers[0];
|
|
23
|
+
if (!base) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
const bound = layers.filter((l) => isValidTextBinding(l.textBinding));
|
|
27
|
+
const write = (layer, parent, indent) => {
|
|
28
|
+
var _a;
|
|
29
|
+
const attrs = [
|
|
30
|
+
parent ? `stackAlign="${(_a = layer.align) !== null && _a !== void 0 ? _a : 'center'}"` : '',
|
|
31
|
+
parent && layer.size !== undefined ? `stackSize={${layer.size}}` : '',
|
|
32
|
+
parent && layer.rotation ? `stackRotation={${layer.rotation}}` : '',
|
|
33
|
+
layer.variant && layer.variant !== (parent === null || parent === void 0 ? void 0 : parent.variant) ? `variant="${layer.variant}"` : '',
|
|
34
|
+
...COLOR_PROPS.map((p) => (layer[p] ? `${p}="${layer[p]}"` : '')),
|
|
35
|
+
layer.textSize !== undefined ? `textSize={${layer.textSize}}` : '',
|
|
36
|
+
]
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.join(' ');
|
|
39
|
+
const open = `${layer.icon}${attrs ? ` ${attrs}` : ''}`;
|
|
40
|
+
const text = isValidTextBinding(layer.textBinding) ? `{${layer.textBinding}}` : layer.text;
|
|
41
|
+
const inner = stackChildrenOf(layers, layer.id);
|
|
42
|
+
if (inner.length === 0) {
|
|
43
|
+
return text ? `${indent}<${open}>${text}</${layer.icon}>` : `${indent}<${open} />`;
|
|
44
|
+
}
|
|
45
|
+
return [
|
|
46
|
+
`${indent}<${open}>`,
|
|
47
|
+
...(text ? [`${indent} ${text}`] : []),
|
|
48
|
+
...inner.map((child) => write(child, layer, `${indent} `)),
|
|
49
|
+
`${indent}</${layer.icon}>`,
|
|
50
|
+
].join('\n');
|
|
51
|
+
};
|
|
52
|
+
const notes = bound.map((l) => `// {${l.textBinding}}: bound text${l.text ? `, e.g. "${l.text}"` : ''}`);
|
|
53
|
+
return [...notes, write(base, undefined, '')].join('\n');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The stack drawn as icons — the base wrapping the layers that sit in it, text innermost (1.3.6).
|
|
57
|
+
* One SVG, as nesting the icons by hand would give.
|
|
58
|
+
*/
|
|
59
|
+
function renderIconStack(layers, icons, { baseProps, values } = {}) {
|
|
60
|
+
const resolve = (name) => (typeof icons === 'function' ? icons(name) : icons[name]);
|
|
61
|
+
const draw = (layer, parent) => {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
const Icon = resolve(layer.icon);
|
|
64
|
+
if (!Icon) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const bound = isValidTextBinding(layer.textBinding) ? values === null || values === void 0 ? void 0 : values[layer.textBinding] : undefined;
|
|
68
|
+
const text = bound !== null && bound !== void 0 ? bound : layer.text;
|
|
69
|
+
const own = {
|
|
70
|
+
primaryColor: layer.primaryColor,
|
|
71
|
+
secondaryColor: layer.secondaryColor,
|
|
72
|
+
accentColor: layer.accentColor,
|
|
73
|
+
textColor: layer.textColor,
|
|
74
|
+
textSize: layer.textSize,
|
|
75
|
+
};
|
|
76
|
+
const inner = stackChildrenOf(layers, layer.id).map((child) => draw(child, layer));
|
|
77
|
+
if (!parent) {
|
|
78
|
+
const props = { ...baseProps };
|
|
79
|
+
for (const [k, v] of Object.entries(own)) {
|
|
80
|
+
if (v !== undefined) {
|
|
81
|
+
props[k] = v;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return (React.createElement(Icon, { ...props, key: layer.id, variant: (_a = layer.variant) !== null && _a !== void 0 ? _a : baseProps === null || baseProps === void 0 ? void 0 : baseProps.variant },
|
|
85
|
+
inner,
|
|
86
|
+
text));
|
|
87
|
+
}
|
|
88
|
+
return (React.createElement(Icon, { ...own, key: layer.id, stackAlign: (_b = layer.align) !== null && _b !== void 0 ? _b : 'center', stackSize: layer.size, stackRotation: layer.rotation, variant: layer.variant !== parent.variant ? layer.variant : undefined },
|
|
89
|
+
inner,
|
|
90
|
+
text));
|
|
91
|
+
};
|
|
92
|
+
return layers[0] ? draw(layers[0], undefined) : null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* NiceIconStack (1.3.6) — draws a stack kept as data (NiceIconStacker's layers) as one icon, its
|
|
96
|
+
* bound text filled from `values`: `<NiceIconStack layers={stack} icons={icons} values={{ count }} />`.
|
|
97
|
+
* The rest of the props go to the base icon.
|
|
98
|
+
*/
|
|
99
|
+
function NiceIconStack({ layers, icons, values, ...baseProps }) {
|
|
100
|
+
return jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderIconStack(layers, icons, { baseProps, values }) });
|
|
101
|
+
}
|
|
102
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
103
|
+
NiceIconStack.displayName = 'NiceIconStack';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
exports.NiceIconStack = NiceIconStack;
|
|
107
|
+
exports.isValidTextBinding = isValidTextBinding;
|
|
108
|
+
exports.niceIconStackCode = niceIconStackCode;
|
|
109
|
+
exports.renderIconStack = renderIconStack;
|
|
110
|
+
exports.stackChildrenOf = stackChildrenOf;
|
|
111
|
+
exports.stackParentId = stackParentId;
|
|
@@ -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 }) => (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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). */
|
package/dist/cjs/icons/ai.js
CHANGED
|
@@ -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;
|