badgecraft 0.3.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +406 -0
  4. package/cli/index.mjs +143 -0
  5. package/cli/render.d.ts +20 -0
  6. package/cli/render.mjs +87 -0
  7. package/cli/studio.mjs +98 -0
  8. package/dist/badge-B-g_9WFj.d.ts +79 -0
  9. package/dist/badge-CCjUxNIG.d.cts +79 -0
  10. package/dist/chunk-3OMN635U.js +44 -0
  11. package/dist/chunk-3OMN635U.js.map +1 -0
  12. package/dist/chunk-BRT5S5PF.cjs +3418 -0
  13. package/dist/chunk-BRT5S5PF.cjs.map +1 -0
  14. package/dist/chunk-EBDSIGZR.cjs +48 -0
  15. package/dist/chunk-EBDSIGZR.cjs.map +1 -0
  16. package/dist/chunk-RRYBMB25.js +3410 -0
  17. package/dist/chunk-RRYBMB25.js.map +1 -0
  18. package/dist/cli-browser.js +526 -0
  19. package/dist/element.cjs +176 -0
  20. package/dist/element.cjs.map +1 -0
  21. package/dist/element.d.cts +31 -0
  22. package/dist/element.d.ts +31 -0
  23. package/dist/element.js +174 -0
  24. package/dist/element.js.map +1 -0
  25. package/dist/index.cjs +47 -0
  26. package/dist/index.cjs.map +1 -0
  27. package/dist/index.d.cts +58 -0
  28. package/dist/index.d.ts +58 -0
  29. package/dist/index.js +17 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/react.cjs +60 -0
  32. package/dist/react.cjs.map +1 -0
  33. package/dist/react.d.cts +29 -0
  34. package/dist/react.d.ts +29 -0
  35. package/dist/react.js +55 -0
  36. package/dist/react.js.map +1 -0
  37. package/dist/studio/assets/badge-9Zq6e9Ht.js +524 -0
  38. package/dist/studio/assets/base-ItCYnbux.css +1 -0
  39. package/dist/studio/assets/base-LFa9cTPp.js +1 -0
  40. package/dist/studio/assets/element-CCTxyf61.js +1 -0
  41. package/dist/studio/assets/index-BVuSTaz-.css +1 -0
  42. package/dist/studio/assets/index-CTTcx2pV.js +28 -0
  43. package/dist/studio/assets/option-keys-CKi71y0n.js +1 -0
  44. package/dist/studio/assets/react-Cq5Erey2.js +9 -0
  45. package/dist/studio/assets/react-DyJFYpWJ.js +1 -0
  46. package/dist/studio/assets/studio-C6plMNOe.css +1 -0
  47. package/dist/studio/assets/studio-DBcSY6tV.js +1 -0
  48. package/dist/studio/assets/style-C2sJ2Xy3.css +1 -0
  49. package/dist/studio/assets/vue-BpGwr3iF.js +1 -0
  50. package/dist/studio/element.html +31 -0
  51. package/dist/studio/env/studio.hdr +5 -0
  52. package/dist/studio/index.html +24 -0
  53. package/dist/studio/logos/apple.svg +1 -0
  54. package/dist/studio/logos/atlassian.svg +1 -0
  55. package/dist/studio/logos/google.svg +1 -0
  56. package/dist/studio/logos/meta.svg +1 -0
  57. package/dist/studio/react.html +16 -0
  58. package/dist/studio/studio.html +27 -0
  59. package/dist/studio/vue.html +15 -0
  60. package/dist/types-CHM3-ZZV.d.cts +204 -0
  61. package/dist/types-CHM3-ZZV.d.ts +204 -0
  62. package/dist/vue.cjs +93 -0
  63. package/dist/vue.cjs.map +1 -0
  64. package/dist/vue.d.cts +115 -0
  65. package/dist/vue.d.ts +115 -0
  66. package/dist/vue.js +87 -0
  67. package/dist/vue.js.map +1 -0
  68. package/docs/cli.md +146 -0
  69. package/docs/gallery.jpg +0 -0
  70. package/docs/performance.md +151 -0
  71. package/docs/render-quality.md +220 -0
  72. package/docs/studio.jpg +0 -0
  73. package/package.json +163 -0
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ export { Badgecraft, createBadge, defaults, environments, framePaths, materials, resolveMaterial } from './chunk-RRYBMB25.js';
2
+
3
+ // src/index.ts
4
+ function isSupported() {
5
+ if (typeof document === "undefined") return false;
6
+ try {
7
+ const gl = document.createElement("canvas").getContext("webgl2");
8
+ gl?.getExtension("WEBGL_lose_context")?.loseContext();
9
+ return !!gl;
10
+ } catch {
11
+ return false;
12
+ }
13
+ }
14
+
15
+ export { isSupported };
16
+ //# sourceMappingURL=index.js.map
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAQO,SAAS,WAAA,GAAuB;AACrC,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,KAAA;AAC5C,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA,CAAE,WAAW,QAAQ,CAAA;AAC/D,IAAA,EAAA,EAAI,YAAA,CAAa,oBAAoB,CAAA,EAAG,WAAA,EAAY;AACpD,IAAA,OAAO,CAAC,CAAC,EAAA;AAAA,EACX,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"index.js","sourcesContent":["export { Badgecraft, createBadge } from './badge'\nexport { materials, resolveMaterial } from './materials'\nexport { environments } from './environment'\nexport { framePaths } from './svg/frames'\nexport { defaults } from './options'\nexport type * from './types'\n\n/** True when the browser can render badges (WebGL2). */\nexport function isSupported(): boolean {\n if (typeof document === 'undefined') return false\n try {\n const gl = document.createElement('canvas').getContext('webgl2')\n gl?.getExtension('WEBGL_lose_context')?.loseContext()\n return !!gl\n } catch {\n return false\n }\n}\n"]}
package/dist/react.cjs ADDED
@@ -0,0 +1,60 @@
1
+ "use client";'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var chunkEBDSIGZR_cjs = require('./chunk-EBDSIGZR.cjs');
6
+ var chunkBRT5S5PF_cjs = require('./chunk-BRT5S5PF.cjs');
7
+ var react = require('react');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ var Badgecraft2 = react.forwardRef(function Badgecraft3(props, ref) {
11
+ const { size, alt, style, className, ...rest } = props;
12
+ const options = chunkEBDSIGZR_cjs.pickOptions(rest);
13
+ const dom = {};
14
+ for (const [key, value] of Object.entries(rest)) if (!chunkEBDSIGZR_cjs.optionKeySet.has(key)) dom[key] = value;
15
+ const hostRef = react.useRef(null);
16
+ const badgeRef = react.useRef(null);
17
+ const initialOptions = react.useRef(options);
18
+ react.useEffect(() => {
19
+ const badge = new chunkBRT5S5PF_cjs.Badgecraft(hostRef.current, initialOptions.current);
20
+ badgeRef.current = badge;
21
+ return () => {
22
+ badge.destroy();
23
+ badgeRef.current = null;
24
+ };
25
+ }, []);
26
+ react.useEffect(() => {
27
+ badgeRef.current?.setOptions(options);
28
+ });
29
+ react.useImperativeHandle(
30
+ ref,
31
+ () => ({
32
+ spin: (turns) => badgeRef.current?.spin(turns),
33
+ glint: () => badgeRef.current?.glint(),
34
+ toDataURL: (type, quality) => badgeRef.current?.toDataURL(type, quality) ?? "",
35
+ toBlob: (type, quality) => badgeRef.current?.toBlob(type, quality) ?? Promise.resolve(null),
36
+ get instance() {
37
+ return badgeRef.current;
38
+ }
39
+ }),
40
+ []
41
+ );
42
+ const dim = chunkEBDSIGZR_cjs.cssSize(size);
43
+ return /* @__PURE__ */ jsxRuntime.jsx(
44
+ "div",
45
+ {
46
+ ...dom,
47
+ ref: hostRef,
48
+ role: props.role ?? "img",
49
+ "aria-label": alt ?? props["aria-label"],
50
+ className,
51
+ style: { display: "inline-block", position: "relative", width: dim, height: dim, ...style }
52
+ }
53
+ );
54
+ });
55
+ var react_default = Badgecraft2;
56
+
57
+ exports.Badgecraft = Badgecraft2;
58
+ exports.default = react_default;
59
+ //# sourceMappingURL=react.cjs.map
60
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/index.tsx"],"names":["Badgecraft","forwardRef","pickOptions","optionKeySet","useRef","useEffect","useImperativeHandle","cssSize","jsx"],"mappings":";;;;;;;;;AA+BO,IAAMA,WAAAA,GAAaC,gBAAA,CAA2C,SAASD,WAAAA,CAAW,OAAO,GAAA,EAAK;AACnG,EAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAK,OAAO,SAAA,EAAW,GAAG,MAAK,GAAI,KAAA;AACjD,EAAA,MAAM,OAAA,GAAUE,8BAAY,IAA+B,CAAA;AAC3D,EAAA,MAAM,MAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,MAAA,CAAO,QAAQ,IAAI,CAAA,EAAG,IAAI,CAACC,+BAAa,GAAA,CAAI,GAAG,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAExF,EAAA,MAAM,OAAA,GAAUC,aAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAWA,aAAqB,IAAI,CAAA;AAC1C,EAAA,MAAM,cAAA,GAAiBA,aAAO,OAAO,CAAA;AAErC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,IAAIL,4BAAA,CAAM,OAAA,CAAQ,OAAA,EAAU,eAAe,OAAO,CAAA;AAChE,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,CAAM,OAAA,EAAQ;AACd,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAAK,eAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,EAAS,WAAW,OAAO,CAAA;AAAA,EACtC,CAAC,CAAA;AAED,EAAAC,yBAAA;AAAA,IACE,GAAA;AAAA,IACA,OAAO;AAAA,MACL,MAAM,CAAC,KAAA,KAAmB,QAAA,CAAS,OAAA,EAAS,KAAK,KAAK,CAAA;AAAA,MACtD,KAAA,EAAO,MAAM,QAAA,CAAS,OAAA,EAAS,KAAA,EAAM;AAAA,MACrC,SAAA,EAAW,CAAC,IAAA,EAAe,OAAA,KAAqB,SAAS,OAAA,EAAS,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA,IAAK,EAAA;AAAA,MAC9F,MAAA,EAAQ,CAAC,IAAA,EAAe,OAAA,KAAqB,QAAA,CAAS,OAAA,EAAS,MAAA,CAAO,IAAA,EAAM,OAAO,CAAA,IAAK,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA;AAAA,MAC5G,IAAI,QAAA,GAAW;AACb,QAAA,OAAO,QAAA,CAAS,OAAA;AAAA,MAClB;AAAA,KACF,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,GAAA,GAAMC,0BAAQ,IAAI,CAAA;AACxB,EAAA,uBACEC,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,GAAA;AAAA,MACJ,GAAA,EAAK,OAAA;AAAA,MACL,IAAA,EAAM,MAAM,IAAA,IAAQ,KAAA;AAAA,MACpB,YAAA,EAAY,GAAA,IAAO,KAAA,CAAM,YAAY,CAAA;AAAA,MACrC,SAAA;AAAA,MACA,KAAA,EAAO,EAAE,OAAA,EAAS,cAAA,EAAgB,QAAA,EAAU,UAAA,EAAY,KAAA,EAAO,GAAA,EAAK,MAAA,EAAQ,GAAA,EAAK,GAAG,KAAA;AAAM;AAAA,GAC5F;AAEJ,CAAC;AAED,IAAO,aAAA,GAAQR","file":"react.cjs","sourcesContent":["import { forwardRef, useEffect, useImperativeHandle, useRef, type CSSProperties, type HTMLAttributes } from 'react'\nimport { Badgecraft as Badge } from '../badge'\nimport { cssSize, optionKeySet, pickOptions } from '../option-keys'\nimport type { BadgeOptions, BadgecraftHandle } from '../types'\n\nexport type * from '../types'\n\nexport interface BadgecraftProps\n extends BadgeOptions,\n Omit<HTMLAttributes<HTMLDivElement>, 'onError' | 'color' | 'children'> {\n /** Width and height of the badge (number = px). Default 160. */\n size?: number | string\n /** Accessible label; the badge is exposed as an image. */\n alt?: string\n className?: string\n style?: CSSProperties\n}\n\nexport interface BadgecraftRef extends BadgecraftHandle {\n glint(): void\n /** The underlying framework-agnostic instance. */\n readonly instance: Badge | null\n}\n\n/**\n * React binding for badgecraft.\n *\n * ```tsx\n * <Badgecraft svg=\"/award.svg\" metal=\"gold\" size={200} />\n * ```\n */\nexport const Badgecraft = forwardRef<BadgecraftRef, BadgecraftProps>(function Badgecraft(props, ref) {\n const { size, alt, style, className, ...rest } = props\n const options = pickOptions(rest as Record<string, unknown>)\n const dom: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(rest)) if (!optionKeySet.has(key)) dom[key] = value\n\n const hostRef = useRef<HTMLDivElement>(null)\n const badgeRef = useRef<Badge | null>(null)\n const initialOptions = useRef(options)\n\n useEffect(() => {\n const badge = new Badge(hostRef.current!, initialOptions.current)\n badgeRef.current = badge\n return () => {\n badge.destroy()\n badgeRef.current = null\n }\n }, [])\n\n // Runs after every render; the core diffs options, so unchanged props cost nothing.\n useEffect(() => {\n badgeRef.current?.setOptions(options)\n })\n\n useImperativeHandle(\n ref,\n () => ({\n spin: (turns?: number) => badgeRef.current?.spin(turns),\n glint: () => badgeRef.current?.glint(),\n toDataURL: (type?: string, quality?: number) => badgeRef.current?.toDataURL(type, quality) ?? '',\n toBlob: (type?: string, quality?: number) => badgeRef.current?.toBlob(type, quality) ?? Promise.resolve(null),\n get instance() {\n return badgeRef.current\n },\n }),\n [],\n )\n\n const dim = cssSize(size)\n return (\n <div\n {...dom}\n ref={hostRef}\n role={props.role ?? 'img'}\n aria-label={alt ?? props['aria-label']}\n className={className}\n style={{ display: 'inline-block', position: 'relative', width: dim, height: dim, ...style }}\n />\n )\n})\n\nexport default Badgecraft\n"]}
@@ -0,0 +1,29 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, CSSProperties } from 'react';
3
+ import { B as Badgecraft$1 } from './badge-CCjUxNIG.cjs';
4
+ import { B as BadgeOptions, b as BadgecraftHandle } from './types-CHM3-ZZV.cjs';
5
+ export { a as BadgeMode, c as BrushDirection, E as EnvironmentInput, d as EnvironmentLight, e as EnvironmentPreset, F as FrameOptions, f as FrameShape, I as IdleAnimation, g as ImageEnvironment, h as Interaction, M as Material, i as MaterialInput, j as MaterialPreset, k as MaterialSlot, P as ProceduralEnvironment, l as ProfileShape, R as ReliefOptions, m as ReliefRole, T as ToneMapping } from './types-CHM3-ZZV.cjs';
6
+
7
+ interface BadgecraftProps extends BadgeOptions, Omit<HTMLAttributes<HTMLDivElement>, 'onError' | 'color' | 'children'> {
8
+ /** Width and height of the badge (number = px). Default 160. */
9
+ size?: number | string;
10
+ /** Accessible label; the badge is exposed as an image. */
11
+ alt?: string;
12
+ className?: string;
13
+ style?: CSSProperties;
14
+ }
15
+ interface BadgecraftRef extends BadgecraftHandle {
16
+ glint(): void;
17
+ /** The underlying framework-agnostic instance. */
18
+ readonly instance: Badgecraft$1 | null;
19
+ }
20
+ /**
21
+ * React binding for badgecraft.
22
+ *
23
+ * ```tsx
24
+ * <Badgecraft svg="/award.svg" metal="gold" size={200} />
25
+ * ```
26
+ */
27
+ declare const Badgecraft: react.ForwardRefExoticComponent<BadgecraftProps & react.RefAttributes<BadgecraftRef>>;
28
+
29
+ export { BadgeOptions, Badgecraft, BadgecraftHandle, type BadgecraftProps, type BadgecraftRef, Badgecraft as default };
@@ -0,0 +1,29 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, CSSProperties } from 'react';
3
+ import { B as Badgecraft$1 } from './badge-B-g_9WFj.js';
4
+ import { B as BadgeOptions, b as BadgecraftHandle } from './types-CHM3-ZZV.js';
5
+ export { a as BadgeMode, c as BrushDirection, E as EnvironmentInput, d as EnvironmentLight, e as EnvironmentPreset, F as FrameOptions, f as FrameShape, I as IdleAnimation, g as ImageEnvironment, h as Interaction, M as Material, i as MaterialInput, j as MaterialPreset, k as MaterialSlot, P as ProceduralEnvironment, l as ProfileShape, R as ReliefOptions, m as ReliefRole, T as ToneMapping } from './types-CHM3-ZZV.js';
6
+
7
+ interface BadgecraftProps extends BadgeOptions, Omit<HTMLAttributes<HTMLDivElement>, 'onError' | 'color' | 'children'> {
8
+ /** Width and height of the badge (number = px). Default 160. */
9
+ size?: number | string;
10
+ /** Accessible label; the badge is exposed as an image. */
11
+ alt?: string;
12
+ className?: string;
13
+ style?: CSSProperties;
14
+ }
15
+ interface BadgecraftRef extends BadgecraftHandle {
16
+ glint(): void;
17
+ /** The underlying framework-agnostic instance. */
18
+ readonly instance: Badgecraft$1 | null;
19
+ }
20
+ /**
21
+ * React binding for badgecraft.
22
+ *
23
+ * ```tsx
24
+ * <Badgecraft svg="/award.svg" metal="gold" size={200} />
25
+ * ```
26
+ */
27
+ declare const Badgecraft: react.ForwardRefExoticComponent<BadgecraftProps & react.RefAttributes<BadgecraftRef>>;
28
+
29
+ export { BadgeOptions, Badgecraft, BadgecraftHandle, type BadgecraftProps, type BadgecraftRef, Badgecraft as default };
package/dist/react.js ADDED
@@ -0,0 +1,55 @@
1
+ "use client";import { pickOptions, optionKeySet, cssSize } from './chunk-3OMN635U.js';
2
+ import { Badgecraft } from './chunk-RRYBMB25.js';
3
+ import { forwardRef, useRef, useEffect, useImperativeHandle } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var Badgecraft2 = forwardRef(function Badgecraft3(props, ref) {
7
+ const { size, alt, style, className, ...rest } = props;
8
+ const options = pickOptions(rest);
9
+ const dom = {};
10
+ for (const [key, value] of Object.entries(rest)) if (!optionKeySet.has(key)) dom[key] = value;
11
+ const hostRef = useRef(null);
12
+ const badgeRef = useRef(null);
13
+ const initialOptions = useRef(options);
14
+ useEffect(() => {
15
+ const badge = new Badgecraft(hostRef.current, initialOptions.current);
16
+ badgeRef.current = badge;
17
+ return () => {
18
+ badge.destroy();
19
+ badgeRef.current = null;
20
+ };
21
+ }, []);
22
+ useEffect(() => {
23
+ badgeRef.current?.setOptions(options);
24
+ });
25
+ useImperativeHandle(
26
+ ref,
27
+ () => ({
28
+ spin: (turns) => badgeRef.current?.spin(turns),
29
+ glint: () => badgeRef.current?.glint(),
30
+ toDataURL: (type, quality) => badgeRef.current?.toDataURL(type, quality) ?? "",
31
+ toBlob: (type, quality) => badgeRef.current?.toBlob(type, quality) ?? Promise.resolve(null),
32
+ get instance() {
33
+ return badgeRef.current;
34
+ }
35
+ }),
36
+ []
37
+ );
38
+ const dim = cssSize(size);
39
+ return /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ ...dom,
43
+ ref: hostRef,
44
+ role: props.role ?? "img",
45
+ "aria-label": alt ?? props["aria-label"],
46
+ className,
47
+ style: { display: "inline-block", position: "relative", width: dim, height: dim, ...style }
48
+ }
49
+ );
50
+ });
51
+ var react_default = Badgecraft2;
52
+
53
+ export { Badgecraft2 as Badgecraft, react_default as default };
54
+ //# sourceMappingURL=react.js.map
55
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/index.tsx"],"names":["Badgecraft"],"mappings":";;;;;AA+BO,IAAMA,WAAAA,GAAa,UAAA,CAA2C,SAASA,WAAAA,CAAW,OAAO,GAAA,EAAK;AACnG,EAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAK,OAAO,SAAA,EAAW,GAAG,MAAK,GAAI,KAAA;AACjD,EAAA,MAAM,OAAA,GAAU,YAAY,IAA+B,CAAA;AAC3D,EAAA,MAAM,MAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,MAAA,CAAO,QAAQ,IAAI,CAAA,EAAG,IAAI,CAAC,aAAa,GAAA,CAAI,GAAG,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAExF,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAqB,IAAI,CAAA;AAC1C,EAAA,MAAM,cAAA,GAAiB,OAAO,OAAO,CAAA;AAErC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,IAAI,UAAA,CAAM,OAAA,CAAQ,OAAA,EAAU,eAAe,OAAO,CAAA;AAChE,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,CAAM,OAAA,EAAQ;AACd,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,EAAS,WAAW,OAAO,CAAA;AAAA,EACtC,CAAC,CAAA;AAED,EAAA,mBAAA;AAAA,IACE,GAAA;AAAA,IACA,OAAO;AAAA,MACL,MAAM,CAAC,KAAA,KAAmB,QAAA,CAAS,OAAA,EAAS,KAAK,KAAK,CAAA;AAAA,MACtD,KAAA,EAAO,MAAM,QAAA,CAAS,OAAA,EAAS,KAAA,EAAM;AAAA,MACrC,SAAA,EAAW,CAAC,IAAA,EAAe,OAAA,KAAqB,SAAS,OAAA,EAAS,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA,IAAK,EAAA;AAAA,MAC9F,MAAA,EAAQ,CAAC,IAAA,EAAe,OAAA,KAAqB,QAAA,CAAS,OAAA,EAAS,MAAA,CAAO,IAAA,EAAM,OAAO,CAAA,IAAK,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA;AAAA,MAC5G,IAAI,QAAA,GAAW;AACb,QAAA,OAAO,QAAA,CAAS,OAAA;AAAA,MAClB;AAAA,KACF,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAI,CAAA;AACxB,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,GAAA;AAAA,MACJ,GAAA,EAAK,OAAA;AAAA,MACL,IAAA,EAAM,MAAM,IAAA,IAAQ,KAAA;AAAA,MACpB,YAAA,EAAY,GAAA,IAAO,KAAA,CAAM,YAAY,CAAA;AAAA,MACrC,SAAA;AAAA,MACA,KAAA,EAAO,EAAE,OAAA,EAAS,cAAA,EAAgB,QAAA,EAAU,UAAA,EAAY,KAAA,EAAO,GAAA,EAAK,MAAA,EAAQ,GAAA,EAAK,GAAG,KAAA;AAAM;AAAA,GAC5F;AAEJ,CAAC;AAED,IAAO,aAAA,GAAQA","file":"react.js","sourcesContent":["import { forwardRef, useEffect, useImperativeHandle, useRef, type CSSProperties, type HTMLAttributes } from 'react'\nimport { Badgecraft as Badge } from '../badge'\nimport { cssSize, optionKeySet, pickOptions } from '../option-keys'\nimport type { BadgeOptions, BadgecraftHandle } from '../types'\n\nexport type * from '../types'\n\nexport interface BadgecraftProps\n extends BadgeOptions,\n Omit<HTMLAttributes<HTMLDivElement>, 'onError' | 'color' | 'children'> {\n /** Width and height of the badge (number = px). Default 160. */\n size?: number | string\n /** Accessible label; the badge is exposed as an image. */\n alt?: string\n className?: string\n style?: CSSProperties\n}\n\nexport interface BadgecraftRef extends BadgecraftHandle {\n glint(): void\n /** The underlying framework-agnostic instance. */\n readonly instance: Badge | null\n}\n\n/**\n * React binding for badgecraft.\n *\n * ```tsx\n * <Badgecraft svg=\"/award.svg\" metal=\"gold\" size={200} />\n * ```\n */\nexport const Badgecraft = forwardRef<BadgecraftRef, BadgecraftProps>(function Badgecraft(props, ref) {\n const { size, alt, style, className, ...rest } = props\n const options = pickOptions(rest as Record<string, unknown>)\n const dom: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(rest)) if (!optionKeySet.has(key)) dom[key] = value\n\n const hostRef = useRef<HTMLDivElement>(null)\n const badgeRef = useRef<Badge | null>(null)\n const initialOptions = useRef(options)\n\n useEffect(() => {\n const badge = new Badge(hostRef.current!, initialOptions.current)\n badgeRef.current = badge\n return () => {\n badge.destroy()\n badgeRef.current = null\n }\n }, [])\n\n // Runs after every render; the core diffs options, so unchanged props cost nothing.\n useEffect(() => {\n badgeRef.current?.setOptions(options)\n })\n\n useImperativeHandle(\n ref,\n () => ({\n spin: (turns?: number) => badgeRef.current?.spin(turns),\n glint: () => badgeRef.current?.glint(),\n toDataURL: (type?: string, quality?: number) => badgeRef.current?.toDataURL(type, quality) ?? '',\n toBlob: (type?: string, quality?: number) => badgeRef.current?.toBlob(type, quality) ?? Promise.resolve(null),\n get instance() {\n return badgeRef.current\n },\n }),\n [],\n )\n\n const dim = cssSize(size)\n return (\n <div\n {...dom}\n ref={hostRef}\n role={props.role ?? 'img'}\n aria-label={alt ?? props['aria-label']}\n className={className}\n style={{ display: 'inline-block', position: 'relative', width: dim, height: dim, ...style }}\n />\n )\n})\n\nexport default Badgecraft\n"]}