@nice2dev/icons 1.3.3 → 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.
- package/CHANGELOG.md +75 -0
- package/README.md +43 -4
- package/dist/cjs/NiceIconStacker.js +120 -0
- package/dist/cjs/client.js +3 -0
- package/dist/cjs/createIcon.js +25 -4
- package/dist/cjs/figmaExport.js +1 -0
- package/dist/cjs/iconParts.js +6 -5
- package/dist/cjs/icons/actions.js +36 -7
- package/dist/cjs/icons/ai.js +3 -0
- package/dist/cjs/icons/business.js +8 -7
- package/dist/cjs/icons/education.js +18 -14
- package/dist/cjs/icons/files.js +34 -15
- package/dist/cjs/icons/index.js +3 -2
- package/dist/cjs/icons/media.js +41 -15
- package/dist/cjs/icons/navigation.js +8 -6
- package/dist/cjs/icons/realestate.js +5 -2
- package/dist/cjs/icons/shapes.js +18 -14
- package/dist/cjs/icons/sustainability.js +2 -11
- package/dist/cjs/icons/travel.js +15 -14
- package/dist/cjs/icons/ui.js +47 -6
- package/dist/cjs/icons/weather.js +3 -0
- package/dist/cjs/index.js +6 -2
- package/dist/cjs/nicetodev-icons.css +1 -1
- package/dist/cjs/stacking.js +100 -0
- package/dist/esm/NiceIconStacker.js +117 -0
- package/dist/esm/client.js +1 -0
- package/dist/esm/createIcon.js +26 -5
- package/dist/esm/figmaExport.js +1 -0
- package/dist/esm/iconParts.js +6 -5
- package/dist/esm/icons/actions.js +36 -7
- package/dist/esm/icons/ai.js +3 -1
- package/dist/esm/icons/business.js +9 -8
- package/dist/esm/icons/education.js +18 -14
- package/dist/esm/icons/files.js +34 -15
- package/dist/esm/icons/index.js +5 -5
- package/dist/esm/icons/media.js +41 -15
- package/dist/esm/icons/navigation.js +8 -6
- package/dist/esm/icons/realestate.js +5 -2
- package/dist/esm/icons/shapes.js +19 -14
- package/dist/esm/icons/sustainability.js +2 -10
- package/dist/esm/icons/travel.js +15 -14
- package/dist/esm/icons/ui.js +47 -7
- package/dist/esm/icons/weather.js +3 -1
- package/dist/esm/index.js +6 -5
- package/dist/esm/nicetodev-icons.css +1 -1
- package/dist/esm/stacking.js +92 -0
- package/dist/types/NiceIconStacker.d.ts +50 -0
- package/dist/types/client.d.ts +2 -0
- package/dist/types/createIcon.d.ts +5 -0
- package/dist/types/iconParts.d.ts +2 -1
- package/dist/types/icons/ai.d.ts +2 -0
- package/dist/types/icons/index.d.ts +5 -5
- package/dist/types/icons/shapes.d.ts +0 -1
- package/dist/types/icons/sustainability.d.ts +0 -1
- package/dist/types/icons/ui.d.ts +1 -0
- package/dist/types/icons/weather.d.ts +2 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/stacking.d.ts +41 -0
- package/dist/types/types.d.ts +31 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,80 @@
|
|
|
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
|
+
|
|
39
|
+
## 1.3.4
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- 15f3a18: Icon browser feedback, round 34:
|
|
44
|
+
|
|
45
|
+
- Twice the stroke width in every variant but `outline`:
|
|
46
|
+
- `NtdMusic`: the stems move left so they still end flush with the note heads.
|
|
47
|
+
- `NtdClock`: the hands.
|
|
48
|
+
- `NtdShare`: the links.
|
|
49
|
+
- `NtdRepeat`: shafts and heads, redrawn tighter so they stay in the box; the shafts stop
|
|
50
|
+
short of the heads' points, so nothing sticks out in `sharp`.
|
|
51
|
+
- `NtdRefresh`: smaller heads, each pointing at the start of the other arrow's tail with a
|
|
52
|
+
clear gap.
|
|
53
|
+
- `NtdWifi`: the inner arc sits further from the dot, the arcs closer together.
|
|
54
|
+
- `NtdList`: dots a quarter smaller.
|
|
55
|
+
- Colours:
|
|
56
|
+
- `NtdHeart`: vivid outlines the split heart in the accent colour instead of an accent seam.
|
|
57
|
+
- `NtdBellRing`: the ring marks are primary when filled, accent in vivid.
|
|
58
|
+
- `NtdBriefcase`: the clasp is in the accent colour with a primary lock square.
|
|
59
|
+
- `NtdSmartphone`: filled, a primary frame round an accent screen with a primary button.
|
|
60
|
+
- Shapes:
|
|
61
|
+
- `NtdBook`: a notch in the right edge beside the pages, leaving a narrow strip of cover.
|
|
62
|
+
- `NtdNotebook`: a wider, shorter cover.
|
|
63
|
+
- `NtdAward`: the ribbon's inside between the two earlier sizes.
|
|
64
|
+
- `NtdApartment`: a thin primary sill under the door when filled.
|
|
65
|
+
- `NtdBus`: a front view with a big windscreen, the driver, headlights and rectangular wheels.
|
|
66
|
+
- `NtdBrush`: redrawn as a paintbrush — handle, ferrule and pointed bristles.
|
|
67
|
+
- Hardcoded colours (`#3B82F6`, white) are gone from `NtdShare` and `NtdRepeat`.
|
|
68
|
+
|
|
69
|
+
- 4fae5a4: `NtdHourglass` and the `turn` animation:
|
|
70
|
+
|
|
71
|
+
- `NtdHourglass`: two plates and a curved glass, the sand running from the top bulb through a
|
|
72
|
+
thread onto a pile in the bottom one. `NiceIcon` resolves it as `hourglass`.
|
|
73
|
+
- `animation="turn"` works on every icon: it turns the icon upside down, holds, turns it back
|
|
74
|
+
and holds again. On `NtdHourglass` the sand pours during the holds, in step with the turns.
|
|
75
|
+
- `animationDuration` now also sets the `--ntd-anim-duration` CSS variable, so parts an icon
|
|
76
|
+
animates inside itself (the hourglass sand) keep the same duration.
|
|
77
|
+
|
|
3
78
|
## 1.3.3
|
|
4
79
|
|
|
5
80
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -193,10 +193,49 @@ Apply an animation by name:
|
|
|
193
193
|
|
|
194
194
|
Each animation maps to a CSS class `.ntd-anim-{name}` defined in `animations.css` (auto-imported).
|
|
195
195
|
|
|
196
|
+
`turn` turns any icon upside down, holds, turns it back and holds again. On `NtdHourglass` the
|
|
197
|
+
sand pours while it holds, in step with the turns at any `animationDuration`:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<NtdHourglass animation="turn" />
|
|
201
|
+
<NtdHourglass animation="turn" animationDuration="6s" />
|
|
202
|
+
```
|
|
203
|
+
|
|
196
204
|
See [Full Animation Catalog](#full-animation-catalog) for the complete list.
|
|
197
205
|
|
|
198
206
|
---
|
|
199
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
|
+
|
|
200
239
|
### Gradient Fills
|
|
201
240
|
|
|
202
241
|
Apply gradient fills using the `gradient` prop with one of 12 built-in presets:
|
|
@@ -406,9 +445,9 @@ Properties passed to every path renderer (pre-resolved from user props):
|
|
|
406
445
|
|
|
407
446
|
`NtdSearch` · `NtdEdit` · `NtdTrash` · `NtdSave` · `NtdDownload` · `NtdUpload` · `NtdShare` · `NtdCopy` · `NtdClipboard` · `NtdPlus` · `NtdMinus` · `NtdCheck` · `NtdFilter` · `NtdSort` · `NtdPrint` · `NtdZoomIn` · `NtdZoomOut` · `NtdUndo` · `NtdRedo` · `NtdLink` · `NtdSettings` · `NtdLogIn` · `NtdLogOut` · `NtdLock` · `NtdUnlock`
|
|
408
447
|
|
|
409
|
-
### UI & Status (
|
|
448
|
+
### UI & Status (27 icons)
|
|
410
449
|
|
|
411
|
-
`NtdHome` · `NtdUser` · `NtdUsers` · `NtdHeart` · `NtdStar` · `NtdBell` · `NtdEye` · `NtdEyeOff` · `NtdInfo` · `NtdWarning` · `NtdError` · `NtdSuccess` · `NtdHelp` · `NtdClock` · `NtdCalendar` · `NtdTag` · `NtdBookmark` · `NtdFlag` · `NtdThumbUp` · `NtdThumbDown` · `NtdShield` · `NtdGlobe` · `NtdMap` · `NtdPin` · `NtdSun` · `NtdMoon`
|
|
450
|
+
`NtdHome` · `NtdUser` · `NtdUsers` · `NtdHeart` · `NtdStar` · `NtdBell` · `NtdEye` · `NtdEyeOff` · `NtdInfo` · `NtdWarning` · `NtdError` · `NtdSuccess` · `NtdHelp` · `NtdClock` · `NtdHourglass` · `NtdCalendar` · `NtdTag` · `NtdBookmark` · `NtdFlag` · `NtdThumbUp` · `NtdThumbDown` · `NtdShield` · `NtdGlobe` · `NtdMap` · `NtdPin` · `NtdSun` · `NtdMoon`
|
|
412
451
|
|
|
413
452
|
### Media & Communication (19 icons)
|
|
414
453
|
|
|
@@ -466,9 +505,9 @@ Properties passed to every path renderer (pre-resolved from user props):
|
|
|
466
505
|
|
|
467
506
|
## Full Animation Catalog
|
|
468
507
|
|
|
469
|
-
### Core Transforms (
|
|
508
|
+
### Core Transforms (14)
|
|
470
509
|
|
|
471
|
-
`spin` · `spin-reverse` · `pulse` · `bounce` · `shake` · `float` · `flip` · `glow` · `wiggle` · `rubber` · `swing` · `tada` · `heartbeat`
|
|
510
|
+
`spin` · `spin-reverse` · `pulse` · `bounce` · `shake` · `float` · `flip` · `glow` · `wiggle` · `rubber` · `swing` · `tada` · `heartbeat` · `turn`
|
|
472
511
|
|
|
473
512
|
### Entrance Animations (22)
|
|
474
513
|
|
|
@@ -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;
|
package/dist/cjs/client.js
CHANGED
|
@@ -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;
|
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, 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();
|
|
@@ -189,7 +193,10 @@ function createIcon(options) {
|
|
|
189
193
|
? `transform ${transition}`
|
|
190
194
|
: undefined;
|
|
191
195
|
const animStyle = {
|
|
192
|
-
|
|
196
|
+
// the variable carries the duration to the parts an icon animates inside itself
|
|
197
|
+
...(animationDuration
|
|
198
|
+
? { animationDuration, '--ntd-anim-duration': animationDuration }
|
|
199
|
+
: {}),
|
|
193
200
|
...(transformString ? { transform: transformString } : {}),
|
|
194
201
|
...(transformString ? { transformOrigin } : {}),
|
|
195
202
|
...(transitionValue ? { transition: transitionValue } : {}),
|
|
@@ -222,7 +229,19 @@ function createIcon(options) {
|
|
|
222
229
|
: variant === 'wireframe'
|
|
223
230
|
? sharpen.wireTree(renderer(renderProps), effectivePrimary)
|
|
224
231
|
: renderer(renderProps);
|
|
225
|
-
|
|
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);
|
|
226
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({
|
|
227
246
|
...renderProps,
|
|
228
247
|
primaryColor: 'black',
|
|
@@ -235,6 +254,8 @@ function createIcon(options) {
|
|
|
235
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)] }));
|
|
236
255
|
});
|
|
237
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;
|
|
238
259
|
return Icon;
|
|
239
260
|
}
|
|
240
261
|
|
package/dist/cjs/figmaExport.js
CHANGED
|
@@ -106,6 +106,7 @@ function exportIconToSvgString(svgElement, options = {}) {
|
|
|
106
106
|
clone.style.animation = '';
|
|
107
107
|
clone.style.animationName = '';
|
|
108
108
|
clone.style.animationDuration = '';
|
|
109
|
+
clone.style.removeProperty('--ntd-anim-duration');
|
|
109
110
|
// Remove SMIL animation elements
|
|
110
111
|
clone.querySelectorAll('animate, animateTransform, animateMotion').forEach((el) => el.remove());
|
|
111
112
|
}
|
package/dist/cjs/iconParts.js
CHANGED
|
@@ -35,17 +35,18 @@ const BELL_CLAPPER_LINE = 'M9 19a3 3 0 006 0';
|
|
|
35
35
|
const BELL_RINGS = 'M2 4l1.5 1.5M22 4l-1.5 1.5';
|
|
36
36
|
/**
|
|
37
37
|
* NtdBell and NtdBellRing, so the two share one bell; `ringing` adds the ring marks. Duotone and
|
|
38
|
-
* vivid are fills only: the bell primary, the clapper
|
|
38
|
+
* vivid are fills only: the bell primary, the clapper secondary. The marks are primary on the solid
|
|
39
|
+
* bell, secondary in duotone and in the accent colour in vivid.
|
|
39
40
|
*/
|
|
40
41
|
function bellIcon(displayName, ringing) {
|
|
41
|
-
const parts = ({ primaryColor,
|
|
42
|
+
const parts = ({ primaryColor, strokeWidth }, detail, rings, ringsOpacity = 1) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: BELL, fill: primaryColor }), jsxRuntime.jsx("path", { d: BELL_CLAPPER, fill: detail }), ringing && (jsxRuntime.jsx("path", { d: BELL_RINGS, stroke: rings, strokeWidth: strokeWidth, opacity: ringsOpacity }))] }));
|
|
42
43
|
return createIcon.createIcon({
|
|
43
44
|
displayName,
|
|
44
45
|
paths: {
|
|
45
|
-
solid: (props) => parts(props, props.primaryColor),
|
|
46
|
+
solid: (props) => parts(props, props.primaryColor, props.primaryColor),
|
|
46
47
|
outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsx("path", { d: `${BELL}${BELL_CLAPPER_LINE}${ringing ? BELL_RINGS : ''}`, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" })),
|
|
47
|
-
duotone: (props) => parts(props, props.secondaryColor),
|
|
48
|
-
vivid: (props) => parts(props, props.secondaryColor),
|
|
48
|
+
duotone: (props) => parts(props, props.secondaryColor, props.secondaryColor),
|
|
49
|
+
vivid: (props) => parts(props, props.secondaryColor, props.accentColor, props.accentOpacity),
|
|
49
50
|
},
|
|
50
51
|
});
|
|
51
52
|
}
|
|
@@ -104,22 +104,51 @@ const NtdUpload = /* @__PURE__ */ createIcon.createIcon({
|
|
|
104
104
|
vivid: ({ primaryColor, secondaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: TRAY, stroke: secondaryColor, strokeWidth: strokeWidth * 2 }), jsxRuntime.jsx("path", { d: "M17 8l-5-5-5 5M12 5v10", stroke: primaryColor, strokeWidth: strokeWidth * 2 })] })),
|
|
105
105
|
},
|
|
106
106
|
});
|
|
107
|
+
// NtdShare: three nodes joined by two links, the links twice the stroke width in every variant but
|
|
108
|
+
// `outline`. Duotone and vivid, fills only: the nodes primary, the links secondary (vivid had a
|
|
109
|
+
// fixed #3B82F6 node and white links that vanished on a light page).
|
|
110
|
+
const SHARE_NODES = 'M18 2a3 3 0 110 6 3 3 0 110-6zM6 9a3 3 0 110 6 3 3 0 110-6zM18 16a3 3 0 110 6 3 3 0 110-6z';
|
|
111
|
+
const SHARE_LINKS = 'M8.59 13.51L15.42 17.49M15.41 6.51L8.59 10.49';
|
|
112
|
+
function shareFilled(nodes, links, strokeWidth) {
|
|
113
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: SHARE_LINKS, stroke: links, strokeWidth: strokeWidth * 2 }), jsxRuntime.jsx("path", { d: SHARE_NODES, fill: nodes })] }));
|
|
114
|
+
}
|
|
107
115
|
const NtdShare = /* @__PURE__ */ createIcon.createIcon({
|
|
108
116
|
displayName: 'NtdShare',
|
|
109
117
|
paths: {
|
|
110
|
-
solid: ({ primaryColor, strokeWidth }) => (
|
|
118
|
+
solid: ({ primaryColor, strokeWidth }) => shareFilled(primaryColor, primaryColor, strokeWidth),
|
|
111
119
|
outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("circle", { cx: "18", cy: "5", r: "2.5", stroke: primaryColor, strokeWidth: strokeWidth * 0.75, fill: "none" }), jsxRuntime.jsx("circle", { cx: "6", cy: "12", r: "2.5", stroke: primaryColor, strokeWidth: strokeWidth * 0.75, fill: "none" }), jsxRuntime.jsx("circle", { cx: "18", cy: "19", r: "2.5", stroke: primaryColor, strokeWidth: strokeWidth * 0.75, fill: "none" }), jsxRuntime.jsx("line", { x1: "8.59", y1: "13.51", x2: "15.42", y2: "17.49", stroke: primaryColor, strokeWidth: strokeWidth * 0.75 }), jsxRuntime.jsx("line", { x1: "15.41", y1: "6.51", x2: "8.59", y2: "10.49", stroke: primaryColor, strokeWidth: strokeWidth * 0.75 })] })),
|
|
112
|
-
duotone: ({ primaryColor, secondaryColor,
|
|
113
|
-
vivid: ({ primaryColor, secondaryColor }) => (
|
|
120
|
+
duotone: ({ primaryColor, secondaryColor, strokeWidth }) => shareFilled(primaryColor, secondaryColor, strokeWidth),
|
|
121
|
+
vivid: ({ primaryColor, secondaryColor, strokeWidth }) => shareFilled(primaryColor, secondaryColor, strokeWidth),
|
|
114
122
|
},
|
|
115
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
|
+
}
|
|
116
143
|
const NtdCopy = /* @__PURE__ */ createIcon.createIcon({
|
|
117
144
|
displayName: 'NtdCopy',
|
|
118
145
|
paths: {
|
|
119
|
-
solid: ({ primaryColor, strokeWidth }) => (
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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),
|
|
123
152
|
},
|
|
124
153
|
});
|
|
125
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;
|
|
@@ -5,21 +5,22 @@ var createIcon = require('../createIcon.js');
|
|
|
5
5
|
var iconParts = require('../iconParts.js');
|
|
6
6
|
|
|
7
7
|
// The band sits halfway down the case and is a cut through it: kept inside the case it meets the
|
|
8
|
-
// sides flush (its round caps stuck out of both). A clasp hangs from its middle: low and wide,
|
|
9
|
-
//
|
|
8
|
+
// sides flush (its round caps stuck out of both). A clasp hangs from its middle: low and wide, in
|
|
9
|
+
// the accent colour like the band on the filled case (secondary in duotone), with a primary lock
|
|
10
|
+
// square in it where it had a slot showing the band through.
|
|
10
11
|
const BRIEFCASE_CASE = { x: 2, y: 7, width: 20, height: 14, rx: 2 };
|
|
11
12
|
const BRIEFCASE_HANDLE = 'M16 7V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v2';
|
|
12
|
-
/** The clasp over the band, hanging down from it
|
|
13
|
+
/** The clasp over the band, hanging down from it. */
|
|
13
14
|
const BRIEFCASE_CLASP = 'M10.6 11.3h2.8a.8.8 0 01.8.8v2.6a.8.8 0 01-.8.8h-2.8a.8.8 0 01-.8-.8v-2.6a.8.8 0 01.8-.8z';
|
|
14
|
-
const
|
|
15
|
+
const BRIEFCASE_LOCK = { x: 11.2, y: 12.6, width: 1.6, height: 1.6 };
|
|
15
16
|
const NtdBriefcase = /* @__PURE__ */ createIcon.createIcon({
|
|
16
17
|
displayName: 'NtdBriefcase',
|
|
17
18
|
paths: {
|
|
18
|
-
solid: (props) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, fill: props.primaryColor }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: props.primaryColor, strokeWidth: props.strokeWidth, fill: "none" }), iconParts.within(props.uid, 'band', jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: props.accentColor, strokeWidth: "1.5", opacity: props.accentOpacity })), jsxRuntime.jsx("path", { d:
|
|
19
|
+
solid: (props) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, fill: props.primaryColor }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: props.primaryColor, strokeWidth: props.strokeWidth, fill: "none" }), iconParts.within(props.uid, 'band', jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: props.accentColor, strokeWidth: "1.5", opacity: props.accentOpacity })), jsxRuntime.jsx("path", { d: BRIEFCASE_CLASP, fill: props.accentColor, opacity: props.accentOpacity }), jsxRuntime.jsx("rect", { ...BRIEFCASE_LOCK, fill: props.primaryColor })] })),
|
|
19
20
|
outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: primaryColor, strokeWidth: "1.5" }), jsxRuntime.jsx("path", { d: BRIEFCASE_CLASP, fill: primaryColor })] })),
|
|
20
21
|
// fills only: the case and the handle primary, the band and the clasp secondary
|
|
21
|
-
duotone: ({ primaryColor, secondaryColor, strokeWidth, uid }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, fill: primaryColor }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), iconParts.within(uid, 'band', jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: secondaryColor, strokeWidth: "1.5" })), jsxRuntime.jsx("path", { d:
|
|
22
|
-
vivid: ({ primaryColor, secondaryColor, accentColor, accentOpacity, strokeWidth, uid }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, fill: primaryColor }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: secondaryColor, strokeWidth: strokeWidth, fill: "none" }), iconParts.within(uid, 'band', jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: secondaryColor, strokeWidth: "1.5" })), jsxRuntime.jsx("path", { d:
|
|
22
|
+
duotone: ({ primaryColor, secondaryColor, strokeWidth, uid }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, fill: primaryColor }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), iconParts.within(uid, 'band', jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: secondaryColor, strokeWidth: "1.5" })), jsxRuntime.jsx("path", { d: BRIEFCASE_CLASP, fill: secondaryColor }), jsxRuntime.jsx("rect", { ...BRIEFCASE_LOCK, fill: primaryColor })] })),
|
|
23
|
+
vivid: ({ primaryColor, secondaryColor, accentColor, accentOpacity, strokeWidth, uid }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE, fill: primaryColor }), jsxRuntime.jsx("path", { d: BRIEFCASE_HANDLE, stroke: secondaryColor, strokeWidth: strokeWidth, fill: "none" }), iconParts.within(uid, 'band', jsxRuntime.jsx("rect", { ...BRIEFCASE_CASE }), jsxRuntime.jsx("line", { x1: "2", y1: "12.5", x2: "22", y2: "12.5", stroke: secondaryColor, strokeWidth: "1.5" })), jsxRuntime.jsx("path", { d: BRIEFCASE_CLASP, fill: accentColor, opacity: accentOpacity }), jsxRuntime.jsx("rect", { ...BRIEFCASE_LOCK, fill: primaryColor })] })),
|
|
23
24
|
},
|
|
24
25
|
});
|
|
25
26
|
// NtdDollar: a line glyph, twice the stroke width in every variant but `outline`; the stem runs
|
|
@@ -46,14 +46,17 @@ const NtdUniversity = /* @__PURE__ */ createIcon.createIcon({
|
|
|
46
46
|
LEARNING TOOLS
|
|
47
47
|
───────────────────────────────────────────────────────────────────────────── */
|
|
48
48
|
// NtdBook: a closed book, not a page — the rounded spine on the left, the block of pages showing
|
|
49
|
-
// at the bottom between the front cover and the
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
// can sit on it;
|
|
53
|
-
|
|
54
|
-
const
|
|
49
|
+
// at the bottom between the front cover and the back cover. Down the right edge it is cover, then
|
|
50
|
+
// a notch cut in 0.9 at the pages, then cover again: beside the pages only a narrow strip of cover
|
|
51
|
+
// is left (it was a 2.5 wide bar). The outline ends the pages with a line short of the edge, the back
|
|
52
|
+
// cover running on under the notch. The cover is plain, so another glyph can sit on it;
|
|
53
|
+
// NtdBookBookmark adds a ribbon.
|
|
54
|
+
const BOOK_SILHOUETTE = 'M7 2h12a1 1 0 011 1v14.2h-.9v2.1H20v.7a1 1 0 01-1 1H7a2.5 2.5 0 01-2.5-2.5v-14A2.5 2.5 0 017 2z';
|
|
55
|
+
const BOOK_PAGES = 'M6.6 17.2h11.4v2.1H6.6a1.05 1.05 0 010-2.1z';
|
|
55
56
|
const BOOK_RIBBON = 'M9.5 2v6.5l1.75-1.3L13 8.5V2z';
|
|
56
|
-
const BOOK_OUTLINE = 'M4.5 18.5v-14A2.5 2.5 0 017 2h12a1 1 0 011
|
|
57
|
+
const BOOK_OUTLINE = 'M4.5 18.5v-14A2.5 2.5 0 017 2h12a1 1 0 011 1v13H7a2.5 2.5 0 000 5h13M18.7 16v5';
|
|
58
|
+
/** The inside of the outline, for duotone's fill under it. */
|
|
59
|
+
const BOOK_OUTLINE_FILL = 'M7 2h12a1 1 0 011 1v13h-1.3v5H7a2.5 2.5 0 01-2.5-2.5v-14A2.5 2.5 0 017 2z';
|
|
57
60
|
/** The book, with the ribbon bookmark or without it. */
|
|
58
61
|
function bookIcon(displayName, ribbon) {
|
|
59
62
|
return createIcon.createIcon({
|
|
@@ -61,7 +64,7 @@ function bookIcon(displayName, ribbon) {
|
|
|
61
64
|
paths: {
|
|
62
65
|
solid: ({ primaryColor, accentColor, accentOpacity }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: BOOK_SILHOUETTE, fill: primaryColor }), jsxRuntime.jsxs("g", { fill: accentColor, opacity: accentOpacity, children: [jsxRuntime.jsx("path", { d: BOOK_PAGES }), ribbon && jsxRuntime.jsx("path", { d: BOOK_RIBBON })] })] })),
|
|
63
66
|
outline: ({ primaryColor, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: BOOK_OUTLINE, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), ribbon && (jsxRuntime.jsx("path", { d: "M9.5 2.5v6l1.75-1.3L13 8.5v-6", stroke: primaryColor, strokeWidth: strokeWidth * 0.75, fill: "none" }))] })),
|
|
64
|
-
duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d:
|
|
67
|
+
duotone: ({ primaryColor, secondaryColor, secondaryOpacity, strokeWidth }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: BOOK_OUTLINE_FILL, fill: secondaryColor, opacity: secondaryOpacity }), jsxRuntime.jsx("path", { d: BOOK_OUTLINE, stroke: primaryColor, strokeWidth: strokeWidth, fill: "none" }), ribbon && jsxRuntime.jsx("path", { d: BOOK_RIBBON, fill: primaryColor })] })),
|
|
65
68
|
vivid: ({ primaryColor, secondaryColor, accentColor, accentOpacity }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: BOOK_SILHOUETTE, fill: primaryColor }), jsxRuntime.jsx("path", { d: BOOK_PAGES, fill: accentColor, opacity: accentOpacity }), ribbon && jsxRuntime.jsx("path", { d: BOOK_RIBBON, fill: secondaryColor })] })),
|
|
66
69
|
},
|
|
67
70
|
});
|
|
@@ -78,12 +81,13 @@ const NtdOpenBook = /* @__PURE__ */ createIcon.createIcon({
|
|
|
78
81
|
},
|
|
79
82
|
});
|
|
80
83
|
// NtdNotebook: a cover with short binder rings across its left edge (they stuck out further) and
|
|
81
|
-
// three lines of writing — in the accent colour when filled, as the outline draws them.
|
|
82
|
-
//
|
|
83
|
-
// the writing
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
const
|
|
84
|
+
// three lines of writing — in the accent colour when filled, as the outline draws them. The cover
|
|
85
|
+
// is 16.5 × 19 (it was 15 × 20, tall and slim for an exercise book). Duotone, fills only: the
|
|
86
|
+
// cover primary, the rings and the writing secondary; vivid: the rings secondary, the writing in
|
|
87
|
+
// the accent colour.
|
|
88
|
+
const NOTEBOOK_COVER = { x: 4.5, y: 2.5, width: 16.5, height: 19, rx: 2 };
|
|
89
|
+
const NOTEBOOK_RINGS = 'M3 6h3M3 10h3M3 14h3M3 18h3';
|
|
90
|
+
const NOTEBOOK_TEXT = 'M9 7.5h8.5M9 11.5h8.5M9 15.5h4.5';
|
|
87
91
|
const NtdNotebook = /* @__PURE__ */ createIcon.createIcon({
|
|
88
92
|
displayName: 'NtdNotebook',
|
|
89
93
|
paths: {
|