@retro-antlitz-kartei/react-editor 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs +121 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +122 -82
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useRef, useEffect, useState, useMemo, useCallback } from 'react';
|
|
2
|
-
import { renderAvatar, normalizeConfig, DEFAULT_CONFIG, configFromSeed,
|
|
2
|
+
import { renderAvatar, normalizeConfig, DEFAULT_CONFIG, configFromSeed, PARTS, partLabel, BG, encodeConfig, SKIN, HAIRS, CLOTH, PANTS, randomConfig, decodeConfig } from '@retro-antlitz-kartei/generator';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { AvatarArena, POSES, POSE_NAMES } from '@retro-antlitz-kartei/animate';
|
|
5
5
|
|
|
@@ -176,7 +176,7 @@ function theme(layout) {
|
|
|
176
176
|
mono: MONO,
|
|
177
177
|
body: BODY,
|
|
178
178
|
radius: "14px",
|
|
179
|
-
titleText: "AVATAR EDITOR",
|
|
179
|
+
titleText: "@retro-antlitz-kartei AVATAR EDITOR",
|
|
180
180
|
glow: false,
|
|
181
181
|
paper: false
|
|
182
182
|
};
|
|
@@ -231,20 +231,37 @@ var FONT_HREFS = [
|
|
|
231
231
|
"https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap"
|
|
232
232
|
];
|
|
233
233
|
var PART_CONTROLS = [
|
|
234
|
-
{ key: "
|
|
235
|
-
{ key: "
|
|
236
|
-
{ key: "
|
|
237
|
-
{ key: "
|
|
238
|
-
{ key: "
|
|
239
|
-
{ key: "
|
|
240
|
-
{ key: "
|
|
241
|
-
{ key: "
|
|
234
|
+
{ key: "build", label: "BUILD" },
|
|
235
|
+
{ key: "hat", label: "HAT" },
|
|
236
|
+
{ key: "hair", label: "HAIR" },
|
|
237
|
+
{ key: "ears", label: "EARS" },
|
|
238
|
+
{ key: "nose", label: "NOSE" },
|
|
239
|
+
{ key: "accessory", label: "ACCESSORY" },
|
|
240
|
+
{ key: "top", label: "TOP" },
|
|
241
|
+
{ key: "trousers", label: "TROUSERS" },
|
|
242
|
+
{ key: "shoes", label: "SHOES" }
|
|
242
243
|
];
|
|
243
244
|
var VIEW_OPTIONS = [
|
|
244
245
|
{ key: "left", name: "LEFT" },
|
|
245
246
|
{ key: "front", name: "FRONT" },
|
|
246
247
|
{ key: "right", name: "RIGHT" }
|
|
247
248
|
];
|
|
249
|
+
function useNarrow(ref, breakpoint = 640) {
|
|
250
|
+
const [narrow, setNarrow] = useState(
|
|
251
|
+
() => typeof window !== "undefined" && window.innerWidth < breakpoint
|
|
252
|
+
);
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
const el = ref.current;
|
|
255
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
256
|
+
const ro = new ResizeObserver((entries) => {
|
|
257
|
+
const w = entries[0]?.contentRect.width ?? 0;
|
|
258
|
+
if (w > 0) setNarrow(w < breakpoint);
|
|
259
|
+
});
|
|
260
|
+
ro.observe(el);
|
|
261
|
+
return () => ro.disconnect();
|
|
262
|
+
}, [ref, breakpoint]);
|
|
263
|
+
return narrow;
|
|
264
|
+
}
|
|
248
265
|
function useControllable(controlled, initial, onChange) {
|
|
249
266
|
const [internal, setInternal] = useState(initial);
|
|
250
267
|
const value = controlled !== void 0 ? controlled : internal;
|
|
@@ -270,6 +287,7 @@ function AvatarEditor(props) {
|
|
|
270
287
|
showCombat = true,
|
|
271
288
|
showCode = true,
|
|
272
289
|
showSeed = true,
|
|
290
|
+
onMagic,
|
|
273
291
|
loadFonts = true,
|
|
274
292
|
className,
|
|
275
293
|
style
|
|
@@ -286,7 +304,10 @@ function AvatarEditor(props) {
|
|
|
286
304
|
const [codeInput, setCodeInput] = useState("");
|
|
287
305
|
const [codeMsg, setCodeMsg] = useState("");
|
|
288
306
|
const [seedInput, setSeedInput] = useState(seed ?? "");
|
|
307
|
+
const stageRef = useRef(null);
|
|
308
|
+
const narrow = useNarrow(stageRef);
|
|
289
309
|
const t = theme(layout);
|
|
310
|
+
const stacked = narrow || t.mainDir === "column";
|
|
290
311
|
useEffect(() => {
|
|
291
312
|
if (!loadFonts || typeof document === "undefined") return;
|
|
292
313
|
for (const href of FONT_HREFS) {
|
|
@@ -296,18 +317,13 @@ function AvatarEditor(props) {
|
|
|
296
317
|
link.href = href;
|
|
297
318
|
document.head.appendChild(link);
|
|
298
319
|
}
|
|
299
|
-
if (!document.getElementById("rak-keyframes")) {
|
|
300
|
-
const s = document.createElement("style");
|
|
301
|
-
s.id = "rak-keyframes";
|
|
302
|
-
s.textContent = "@keyframes rak-coinpulse{0%,100%{transform:translateY(0)}50%{transform:translateY(-2px)}}";
|
|
303
|
-
document.head.appendChild(s);
|
|
304
|
-
}
|
|
305
320
|
}, [loadFonts]);
|
|
306
321
|
const patch = useCallback((p) => setConfig({ ...config, ...p }), [config, setConfig]);
|
|
307
322
|
const cycle = useCallback(
|
|
308
323
|
(key, dir) => {
|
|
309
|
-
const
|
|
310
|
-
|
|
324
|
+
const ids = PARTS[key];
|
|
325
|
+
const cur = ids.indexOf(config[key]);
|
|
326
|
+
patch({ [key]: ids[(cur + dir + ids.length) % ids.length] });
|
|
311
327
|
},
|
|
312
328
|
[config, patch]
|
|
313
329
|
);
|
|
@@ -398,24 +414,25 @@ function AvatarEditor(props) {
|
|
|
398
414
|
border: "2px solid " + (active ? t.accent : t.paper ? "#00000033" : "#ffffff44"),
|
|
399
415
|
boxShadow: active ? "0 0 0 2px " + t.accent + "66" : "none"
|
|
400
416
|
});
|
|
401
|
-
const nameDisplay =
|
|
417
|
+
const nameDisplay = partLabel("top", config.top).toUpperCase();
|
|
402
418
|
const partRow = (key, label) => /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
|
|
403
419
|
/* @__PURE__ */ jsx("button", { onClick: () => cycle(key, -1), style: arrowStyle, children: "\u25C0" }),
|
|
404
420
|
/* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, textAlign: "center" }, children: [
|
|
405
421
|
/* @__PURE__ */ jsx("div", { style: partLabelStyle, children: label }),
|
|
406
|
-
/* @__PURE__ */ jsx("div", { style: partValueStyle, children:
|
|
422
|
+
/* @__PURE__ */ jsx("div", { style: partValueStyle, children: partLabel(key, config[key]) })
|
|
407
423
|
] }),
|
|
408
424
|
/* @__PURE__ */ jsx("button", { onClick: () => cycle(key, 1), style: arrowStyle, children: "\u25B6" })
|
|
409
425
|
] }, key);
|
|
410
426
|
return /* @__PURE__ */ jsxs(
|
|
411
427
|
"div",
|
|
412
428
|
{
|
|
429
|
+
ref: stageRef,
|
|
413
430
|
className,
|
|
414
431
|
style: {
|
|
415
432
|
minHeight: "100%",
|
|
416
433
|
width: "100%",
|
|
417
434
|
background: t.stageBg,
|
|
418
|
-
padding: "24px",
|
|
435
|
+
padding: narrow ? "10px" : "24px",
|
|
419
436
|
display: "flex",
|
|
420
437
|
flexDirection: "column",
|
|
421
438
|
alignItems: "center",
|
|
@@ -452,11 +469,11 @@ function AvatarEditor(props) {
|
|
|
452
469
|
{
|
|
453
470
|
style: {
|
|
454
471
|
width: "100%",
|
|
455
|
-
maxWidth: t.mainDir === "row" ? "860px" : "540px",
|
|
472
|
+
maxWidth: narrow ? "100%" : t.mainDir === "row" ? "860px" : "540px",
|
|
456
473
|
background: t.cabinet,
|
|
457
|
-
border: "4px solid " + t.cabinetBorder,
|
|
458
|
-
borderRadius: t.radius,
|
|
459
|
-
boxShadow: "0 18px 50px rgba(0,0,0,.5)" + (t.glow ? ", 0 0 30px " + t.accent + "33" : ""),
|
|
474
|
+
border: narrow ? "none" : "4px solid " + t.cabinetBorder,
|
|
475
|
+
borderRadius: narrow ? "10px" : t.radius,
|
|
476
|
+
boxShadow: narrow ? "none" : "0 18px 50px rgba(0,0,0,.5)" + (t.glow ? ", 0 0 30px " + t.accent + "33" : ""),
|
|
460
477
|
overflow: "hidden"
|
|
461
478
|
},
|
|
462
479
|
children: [
|
|
@@ -465,29 +482,32 @@ function AvatarEditor(props) {
|
|
|
465
482
|
{
|
|
466
483
|
style: {
|
|
467
484
|
background: t.marqueeBg,
|
|
468
|
-
padding: "14px",
|
|
485
|
+
padding: narrow ? "10px" : "14px",
|
|
469
486
|
display: "flex",
|
|
470
|
-
gap: "12px",
|
|
487
|
+
gap: narrow ? "8px" : "12px",
|
|
471
488
|
alignItems: "center",
|
|
472
489
|
justifyContent: "center",
|
|
473
|
-
|
|
490
|
+
flexWrap: "wrap",
|
|
491
|
+
borderBottom: narrow ? "none" : "3px solid " + t.cabinetBorder
|
|
474
492
|
},
|
|
475
493
|
children: [
|
|
476
|
-
/* @__PURE__ */ jsx("span", { style: { width: "10px", height: "10px", borderRadius: "50%", background: t.accent, boxShadow: "0 0 8px " + t.accent } }),
|
|
494
|
+
/* @__PURE__ */ jsx("span", { style: { width: "10px", height: "10px", borderRadius: "50%", background: t.accent, boxShadow: "0 0 8px " + t.accent, flex: "0 0 auto" } }),
|
|
477
495
|
/* @__PURE__ */ jsx(
|
|
478
496
|
"span",
|
|
479
497
|
{
|
|
480
498
|
style: {
|
|
481
499
|
fontFamily: t.mono,
|
|
482
|
-
fontSize: t.titleText === "WANTED" ? "20px" : "15px",
|
|
500
|
+
fontSize: t.titleText === "WANTED" ? "20px" : narrow ? "10px" : "15px",
|
|
483
501
|
color: t.title,
|
|
484
|
-
letterSpacing: "2px",
|
|
485
|
-
textShadow: t.glow ? "0 0 10px " + t.accent : "2px 2px 0 #00000044"
|
|
502
|
+
letterSpacing: narrow ? "1px" : "2px",
|
|
503
|
+
textShadow: t.glow ? "0 0 10px " + t.accent : "2px 2px 0 #00000044",
|
|
504
|
+
textAlign: "center",
|
|
505
|
+
lineHeight: 1.5
|
|
486
506
|
},
|
|
487
507
|
children: t.titleText
|
|
488
508
|
}
|
|
489
509
|
),
|
|
490
|
-
/* @__PURE__ */ jsx("span", { style: { width: "10px", height: "10px", borderRadius: "50%", background: t.accent, boxShadow: "0 0 8px " + t.accent } })
|
|
510
|
+
/* @__PURE__ */ jsx("span", { style: { width: "10px", height: "10px", borderRadius: "50%", background: t.accent, boxShadow: "0 0 8px " + t.accent, flex: "0 0 auto" } })
|
|
491
511
|
]
|
|
492
512
|
}
|
|
493
513
|
),
|
|
@@ -496,21 +516,23 @@ function AvatarEditor(props) {
|
|
|
496
516
|
{
|
|
497
517
|
style: {
|
|
498
518
|
display: "flex",
|
|
499
|
-
flexDirection:
|
|
519
|
+
flexDirection: stacked ? "column" : "row",
|
|
500
520
|
gap: "16px",
|
|
501
|
-
padding: "18px",
|
|
502
|
-
alignItems:
|
|
521
|
+
padding: narrow ? "10px" : "18px",
|
|
522
|
+
alignItems: stacked ? "center" : "stretch"
|
|
503
523
|
},
|
|
504
524
|
children: [
|
|
505
525
|
/* @__PURE__ */ jsxs(
|
|
506
526
|
"div",
|
|
507
527
|
{
|
|
508
528
|
style: {
|
|
509
|
-
flex:
|
|
529
|
+
flex: stacked ? "0 0 auto" : "0 0 300px",
|
|
510
530
|
display: "flex",
|
|
511
531
|
flexDirection: "column",
|
|
512
532
|
gap: "8px",
|
|
513
|
-
alignItems: "center"
|
|
533
|
+
alignItems: "center",
|
|
534
|
+
width: stacked ? "100%" : void 0,
|
|
535
|
+
maxWidth: "100%"
|
|
514
536
|
},
|
|
515
537
|
children: [
|
|
516
538
|
/* @__PURE__ */ jsxs(
|
|
@@ -527,7 +549,15 @@ function AvatarEditor(props) {
|
|
|
527
549
|
},
|
|
528
550
|
onClick: showCombat ? () => setModalOpen(true) : void 0,
|
|
529
551
|
children: [
|
|
530
|
-
/* @__PURE__ */ jsx(
|
|
552
|
+
/* @__PURE__ */ jsx(
|
|
553
|
+
AvatarPreview,
|
|
554
|
+
{
|
|
555
|
+
config,
|
|
556
|
+
width: 320,
|
|
557
|
+
height: 400,
|
|
558
|
+
style: { width: "264px", maxWidth: "100%", height: "auto", aspectRatio: "320 / 400", borderRadius: "3px" }
|
|
559
|
+
}
|
|
560
|
+
),
|
|
531
561
|
/* @__PURE__ */ jsx(
|
|
532
562
|
"div",
|
|
533
563
|
{
|
|
@@ -602,10 +632,10 @@ function AvatarEditor(props) {
|
|
|
602
632
|
},
|
|
603
633
|
o.key
|
|
604
634
|
)) }),
|
|
605
|
-
partRow("
|
|
635
|
+
partRow("mouth", "MOUTH"),
|
|
606
636
|
/* @__PURE__ */ jsxs("div", { style: swatchRowStyle, children: [
|
|
607
637
|
/* @__PURE__ */ jsx("span", { style: swatchLabelStyle, children: "BACKGROUND" }),
|
|
608
|
-
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: BG.map((c
|
|
638
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: BG.map((c) => /* @__PURE__ */ jsx("button", { onClick: () => patch({ background: c }), style: swatchBtn(c, config.background === c) }, c)) })
|
|
609
639
|
] }),
|
|
610
640
|
showCode && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
611
641
|
/* @__PURE__ */ jsx("div", { style: dividerStyle }),
|
|
@@ -664,7 +694,7 @@ function AvatarEditor(props) {
|
|
|
664
694
|
style: {
|
|
665
695
|
flex: 1,
|
|
666
696
|
minWidth: 0,
|
|
667
|
-
width:
|
|
697
|
+
width: stacked ? "100%" : "auto",
|
|
668
698
|
display: "flex",
|
|
669
699
|
flexDirection: "column",
|
|
670
700
|
gap: "9px",
|
|
@@ -678,56 +708,66 @@ function AvatarEditor(props) {
|
|
|
678
708
|
/* @__PURE__ */ jsx("div", { style: dividerStyle }),
|
|
679
709
|
/* @__PURE__ */ jsxs("div", { style: swatchRowStyle, children: [
|
|
680
710
|
/* @__PURE__ */ jsx("span", { style: swatchLabelStyle, children: "SKIN" }),
|
|
681
|
-
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: SKIN.map((c
|
|
711
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: SKIN.map((c) => /* @__PURE__ */ jsx("button", { onClick: () => patch({ skin: c }), style: swatchBtn(c, config.skin === c) }, c)) })
|
|
712
|
+
] }),
|
|
713
|
+
/* @__PURE__ */ jsxs("div", { style: swatchRowStyle, children: [
|
|
714
|
+
/* @__PURE__ */ jsx("span", { style: swatchLabelStyle, children: "HAIR" }),
|
|
715
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: HAIRS.map((c) => /* @__PURE__ */ jsx("button", { onClick: () => patch({ hairColor: c }), style: swatchBtn(c, config.hairColor === c) }, c)) })
|
|
682
716
|
] }),
|
|
683
717
|
/* @__PURE__ */ jsxs("div", { style: swatchRowStyle, children: [
|
|
684
718
|
/* @__PURE__ */ jsx("span", { style: swatchLabelStyle, children: "CLOTHING" }),
|
|
685
|
-
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: CLOTH.map((c
|
|
719
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: CLOTH.map((c) => /* @__PURE__ */ jsx("button", { onClick: () => patch({ topColor: c }), style: swatchBtn(c, config.topColor === c) }, c)) })
|
|
720
|
+
] }),
|
|
721
|
+
/* @__PURE__ */ jsxs("div", { style: swatchRowStyle, children: [
|
|
722
|
+
/* @__PURE__ */ jsx("span", { style: swatchLabelStyle, children: "TROUSERS" }),
|
|
723
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: PANTS.map((c) => /* @__PURE__ */ jsx("button", { onClick: () => patch({ trousersColor: c }), style: swatchBtn(c, config.trousersColor === c) }, c)) })
|
|
686
724
|
] }),
|
|
687
725
|
/* @__PURE__ */ jsx("div", { style: dividerStyle }),
|
|
688
|
-
/* @__PURE__ */
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
726
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", marginTop: "2px" }, children: [
|
|
727
|
+
onMagic && /* @__PURE__ */ jsx(
|
|
728
|
+
"button",
|
|
729
|
+
{
|
|
730
|
+
onClick: onMagic,
|
|
731
|
+
style: {
|
|
732
|
+
fontFamily: t.mono,
|
|
733
|
+
fontSize: "10px",
|
|
734
|
+
letterSpacing: "1px",
|
|
735
|
+
cursor: "pointer",
|
|
736
|
+
padding: "12px",
|
|
737
|
+
borderRadius: t.paper ? "3px" : "9px",
|
|
738
|
+
border: "3px solid " + t.title,
|
|
739
|
+
background: "#9b5de5",
|
|
740
|
+
color: "#fff",
|
|
741
|
+
flex: "0 0 auto"
|
|
742
|
+
},
|
|
743
|
+
children: "\u2728 MAGIC"
|
|
744
|
+
}
|
|
745
|
+
),
|
|
746
|
+
/* @__PURE__ */ jsx(
|
|
747
|
+
"button",
|
|
748
|
+
{
|
|
749
|
+
onClick: onRandom,
|
|
750
|
+
style: {
|
|
751
|
+
fontFamily: t.mono,
|
|
752
|
+
fontSize: "10px",
|
|
753
|
+
letterSpacing: "1px",
|
|
754
|
+
cursor: "pointer",
|
|
755
|
+
padding: "12px",
|
|
756
|
+
borderRadius: t.paper ? "3px" : "9px",
|
|
757
|
+
border: "3px solid " + t.title,
|
|
758
|
+
background: t.accent,
|
|
759
|
+
color: "#10131c",
|
|
760
|
+
flex: 1
|
|
761
|
+
},
|
|
762
|
+
children: "\u{1F3B2} RANDOM"
|
|
763
|
+
}
|
|
764
|
+
)
|
|
765
|
+
] })
|
|
707
766
|
]
|
|
708
767
|
}
|
|
709
768
|
)
|
|
710
769
|
]
|
|
711
770
|
}
|
|
712
|
-
),
|
|
713
|
-
/* @__PURE__ */ jsxs(
|
|
714
|
-
"div",
|
|
715
|
-
{
|
|
716
|
-
style: {
|
|
717
|
-
background: t.marqueeBg,
|
|
718
|
-
padding: "10px",
|
|
719
|
-
display: "flex",
|
|
720
|
-
gap: "10px",
|
|
721
|
-
alignItems: "center",
|
|
722
|
-
justifyContent: "center",
|
|
723
|
-
color: t.title,
|
|
724
|
-
borderTop: "3px solid " + t.cabinetBorder
|
|
725
|
-
},
|
|
726
|
-
children: [
|
|
727
|
-
/* @__PURE__ */ jsx("span", { style: { color: t.accent, fontSize: "14px", animation: "rak-coinpulse 1.2s ease-in-out infinite" }, children: "\u25CF" }),
|
|
728
|
-
/* @__PURE__ */ jsx("span", { style: { fontFamily: t.mono, fontSize: "8px", letterSpacing: "1px" }, children: "INSERT COIN \xB7 SATIRE EDITION" })
|
|
729
|
-
]
|
|
730
|
-
}
|
|
731
771
|
)
|
|
732
772
|
]
|
|
733
773
|
}
|