@agot/card-preview 1.0.0 → 1.0.2

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 CHANGED
@@ -1,16 +1,31 @@
1
- # @throneteki-playtesting/card-preview
1
+ # @agot/card-preview
2
2
 
3
- A lightweight React component library for rendering **A Game of Thrones LCG 2nd Edition** cards.
4
-
5
- This library is installed directly from GitHub.
3
+ A React component library for rendering **A Game of Thrones LCG 2nd Edition** cards. It requires data in an `IRenderCard` format.
6
4
 
7
5
  ## 📦 Installation
8
6
 
9
- To add this package to your project, run the following command:
10
-
11
7
  ```bash
12
- # Install the latest from the master branch:
13
- npm install throneteki-playtesting/got-automation#master:@agotCardPreview
8
+ npm install @agot/card-preview
9
+ ```
10
+
11
+ ### Peer Dependencies
12
+ Ensure your host project has the following installed:
13
+ * **react** (^19.1.0)
14
+
15
+ ---
16
+
17
+ ## 🛠 Usage
18
+
19
+ Import the `CardPreview` component and provide an `IRenderCard` to display the corresponding card image and data.
20
+
21
+ ```tsx
22
+ import { CardPreview } from '@agot/card-preview';
14
23
 
15
- # Install a specific version (Recommended for stability):
16
- npm install throneteki-playtesting/got-automation#v1.1.0:@agotCardPreview
24
+ const App = () => {
25
+ return (
26
+ <CardPreview
27
+ card={{ ... }}
28
+ />
29
+ );
30
+ };
31
+ ```
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  type DeepPartial<T> = T extends (infer U)[] ? DeepPartial<U>[] | undefined : T extends object ? {
5
6
  [P in keyof T]?: DeepPartial<T[P]>;
@@ -71,8 +72,30 @@ type CardComponentProps = Omit<BaseElementProps, "children"> & {
71
72
  scale?: number;
72
73
  orientation?: "horizontal" | "vertical";
73
74
  rounded?: boolean;
75
+ classNames?: {
76
+ wrapper?: string;
77
+ inner?: string;
78
+ };
79
+ styles?: {
80
+ wrapper?: CSSProperties;
81
+ inner?: CSSProperties;
82
+ };
74
83
  } & React.DOMAttributes<HTMLDivElement>;
75
84
 
76
- declare const CardPreview: ({ card, scale, orientation, rounded, className, style, ...props }: CardComponentProps) => react_jsx_runtime.JSX.Element;
85
+ declare const CardPreview: react.MemoExoticComponent<({ card, scale, orientation, rounded, className, style, ...props }: CardComponentProps) => react_jsx_runtime.JSX.Element>;
86
+ declare const CardBlank: react.MemoExoticComponent<({ children, scale, orientation, rounded, className, classNames: classGroups, style, styles: styleGroups, ...props }: BaseElementProps & {
87
+ classNames?: {
88
+ wrapper?: string;
89
+ inner?: string;
90
+ };
91
+ styles?: {
92
+ wrapper?: react.CSSProperties;
93
+ inner?: react.CSSProperties;
94
+ };
95
+ scale?: number;
96
+ orientation?: "vertical" | "horizontal";
97
+ rotated?: boolean;
98
+ rounded?: boolean;
99
+ } & react.DOMAttributes<HTMLDivElement>) => react_jsx_runtime.JSX.Element>;
77
100
 
78
- export { CardPreview as default };
101
+ export { CardBlank, CardPreview };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  type DeepPartial<T> = T extends (infer U)[] ? DeepPartial<U>[] | undefined : T extends object ? {
5
6
  [P in keyof T]?: DeepPartial<T[P]>;
@@ -71,8 +72,30 @@ type CardComponentProps = Omit<BaseElementProps, "children"> & {
71
72
  scale?: number;
72
73
  orientation?: "horizontal" | "vertical";
73
74
  rounded?: boolean;
75
+ classNames?: {
76
+ wrapper?: string;
77
+ inner?: string;
78
+ };
79
+ styles?: {
80
+ wrapper?: CSSProperties;
81
+ inner?: CSSProperties;
82
+ };
74
83
  } & React.DOMAttributes<HTMLDivElement>;
75
84
 
76
- declare const CardPreview: ({ card, scale, orientation, rounded, className, style, ...props }: CardComponentProps) => react_jsx_runtime.JSX.Element;
85
+ declare const CardPreview: react.MemoExoticComponent<({ card, scale, orientation, rounded, className, style, ...props }: CardComponentProps) => react_jsx_runtime.JSX.Element>;
86
+ declare const CardBlank: react.MemoExoticComponent<({ children, scale, orientation, rounded, className, classNames: classGroups, style, styles: styleGroups, ...props }: BaseElementProps & {
87
+ classNames?: {
88
+ wrapper?: string;
89
+ inner?: string;
90
+ };
91
+ styles?: {
92
+ wrapper?: react.CSSProperties;
93
+ inner?: react.CSSProperties;
94
+ };
95
+ scale?: number;
96
+ orientation?: "vertical" | "horizontal";
97
+ rotated?: boolean;
98
+ rounded?: boolean;
99
+ } & react.DOMAttributes<HTMLDivElement>) => react_jsx_runtime.JSX.Element>;
77
100
 
78
- export { CardPreview as default };
101
+ export { CardBlank, CardPreview };
package/dist/index.js CHANGED
@@ -30,12 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.tsx
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- default: () => index_default
33
+ CardBlank: () => CardBlank,
34
+ CardPreview: () => CardPreview
34
35
  });
35
36
  module.exports = __toCommonJS(index_exports);
36
37
 
37
38
  // src/components/cardComponents.tsx
38
- var import_classnames2 = __toESM(require("classnames"));
39
+ var import_classnames = __toESM(require("classnames"));
39
40
 
40
41
  // ../common/models/cards.ts
41
42
  var challengeIcons = ["military", "intrigue", "power"];
@@ -55,6 +56,14 @@ var import_react = require("react");
55
56
  // src/utils.ts
56
57
  var px = (value) => `${value}px`;
57
58
  var em = (value) => `${value}em`;
59
+ var BASE_WIDTH = 240;
60
+ var BASE_HEIGHT = 333;
61
+ var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
62
+ var divisor = gcd(BASE_WIDTH, BASE_HEIGHT);
63
+ var ASPECT_RATIO = {
64
+ width: BASE_WIDTH / divisor,
65
+ height: BASE_HEIGHT / divisor
66
+ };
58
67
 
59
68
  // src/components/autoSize.tsx
60
69
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -102,9 +111,6 @@ var autoSize_default = AutoSize;
102
111
  // src/components/cardComponents.tsx
103
112
  var import_react2 = require("react");
104
113
 
105
- // ../client/src/components/thronesIcon.tsx
106
- var import_classnames = __toESM(require("classnames"), 1);
107
-
108
114
  // ../common/utils.ts
109
115
  var thronesColors = {
110
116
  "baratheon": "#e3d852",
@@ -146,63 +152,92 @@ var thronesIcons = {
146
152
  agenda: "\uE611"
147
153
  };
148
154
 
149
- // ../client/src/components/thronesIcon.tsx
155
+ // src/components/thronesIcon.tsx
150
156
  var import_jsx_runtime2 = require("react/jsx-runtime");
151
157
  var ThronesIcon = ({ name, className, style, visible = true }) => {
152
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: (0, import_classnames.default)("font-thronesdb leading-none", { invisible: !visible, "leading-relaxed": name === "unique" }, className), style, children: thronesIcons[name] });
158
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className, style: {
159
+ fontFamily: "thronesdb",
160
+ ...!visible && { visibility: "hidden" },
161
+ lineHeight: name === "unique" ? 1.625 : 1,
162
+ ...style
163
+ }, children: thronesIcons[name] });
153
164
  };
154
165
  var thronesIcon_default = ThronesIcon;
155
166
 
156
167
  // src/components/cardComponents.tsx
157
168
  var import_jsx_runtime3 = require("react/jsx-runtime");
169
+ var CardWrapper = (0, import_react2.memo)(({ children, scale = 1, orientation = "vertical", rounded = false, className, classNames: classGroups, style, styles: styleGroups, ...props }) => {
170
+ const wrapperRef = (0, import_react2.useRef)(null);
171
+ const [renderedWidth, setRenderedWidth] = (0, import_react2.useState)(BASE_WIDTH * scale);
172
+ (0, import_react2.useLayoutEffect)(() => {
173
+ const element = wrapperRef.current;
174
+ if (!element) return;
175
+ const observer = new ResizeObserver((entries) => {
176
+ for (const entry of entries) {
177
+ const width = entry.contentRect.width;
178
+ if (width > 0) {
179
+ setRenderedWidth(width * scale);
180
+ }
181
+ }
182
+ });
183
+ observer.observe(element);
184
+ return () => observer.disconnect();
185
+ }, [scale]);
186
+ const dynamicScale = (0, import_react2.useMemo)(() => {
187
+ const baseWidth = orientation === "horizontal" ? BASE_HEIGHT : BASE_WIDTH;
188
+ return renderedWidth / baseWidth;
189
+ }, [orientation, renderedWidth]);
190
+ const aspectRatio = (0, import_react2.useMemo)(() => orientation === "horizontal" ? `${ASPECT_RATIO.height}/${ASPECT_RATIO.width}` : `${ASPECT_RATIO.width}/${ASPECT_RATIO.height}`, [orientation]);
191
+ const wrapperStyle = (0, import_react2.useMemo)(() => ({
192
+ overflow: "hidden",
193
+ position: "relative",
194
+ aspectRatio,
195
+ width: "100%",
196
+ height: "100%",
197
+ ...rounded && { borderRadius: px(12 * dynamicScale) },
198
+ ...style,
199
+ ...styleGroups?.wrapper
200
+ }), [aspectRatio, dynamicScale, rounded, style, styleGroups?.wrapper]);
201
+ const innerStyle = (0, import_react2.useMemo)(() => ({
202
+ width: px(BASE_WIDTH),
203
+ height: px(BASE_HEIGHT),
204
+ transform: `scale(${dynamicScale})`,
205
+ transformOrigin: "top left",
206
+ position: "absolute",
207
+ top: 0,
208
+ left: 0,
209
+ ...styleGroups?.inner
210
+ }), [dynamicScale, styleGroups?.inner]);
211
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: wrapperRef, className: (0, import_classnames.default)(className, classGroups?.wrapper), style: wrapperStyle, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: classGroups?.inner, style: innerStyle, children }) });
212
+ });
158
213
  var defaultOrientation = (type) => type === "plot" ? "horizontal" : "vertical";
159
- var Card = (0, import_react2.memo)(({ children, card, orientation = defaultOrientation(card.type), scale = 1, rounded = true, className, classNames: classGroups, style, styles: styleGroups, ...props }) => {
160
- const width = 240;
161
- const height = 333;
162
- const wrapperWidth = orientation === "horizontal" ? height : width;
163
- const wrapperHeight = orientation === "horizontal" ? width : height;
164
- const innerWidth = card.type === "plot" ? height : width;
165
- const innerHeight = card.type === "plot" ? width : height;
166
- const rotate = orientation !== defaultOrientation(card.type);
167
- const innerStyle = (0, import_react2.useMemo)(() => {
168
- const style2 = {
169
- borderColor: card.faction ? thronesColors[card.faction] : "white",
170
- background: "white",
171
- color: "black",
172
- fontFamily: "Open Sans, sans-serif",
173
- ...scale !== 1 && { scale },
174
- ...(scale !== 1 || rotate) && { transformOrigin: "top left" },
175
- ...rotate && { position: "relative", rotate: "270deg", top: "100%" },
176
- ...styleGroups?.inner
177
- };
178
- return style2;
179
- }, [card.faction, rotate, scale, styleGroups?.inner]);
214
+ var Card = (0, import_react2.memo)(({ children, card, orientation = defaultOrientation(card.type), rounded = true, scale = 1, className, classNames: classGroups, style, styles: styleGroups, ...props }) => {
215
+ const innerWidth = card.type === "plot" ? BASE_HEIGHT : BASE_WIDTH;
216
+ const innerHeight = card.type === "plot" ? BASE_WIDTH : BASE_HEIGHT;
217
+ const rotated = orientation !== defaultOrientation(card.type);
218
+ const innerStyle = (0, import_react2.useMemo)(() => ({
219
+ width: px(innerWidth),
220
+ height: px(innerHeight),
221
+ borderWidth: px(12),
222
+ borderColor: card.faction ? thronesColors[card.faction] : "white",
223
+ background: "white",
224
+ color: "black",
225
+ fontFamily: "Open Sans, sans-serif",
226
+ ...rotated && { rotate: "270deg", top: "100%" },
227
+ ...styleGroups?.inner
228
+ }), [card.faction, innerHeight, innerWidth, rotated, styleGroups?.inner]);
180
229
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
181
- "div",
230
+ CardWrapper,
182
231
  {
183
- className: (0, import_classnames2.default)(className, classGroups?.wrapper),
184
- style: {
185
- overflow: "hidden",
186
- width: px(wrapperWidth * scale),
187
- height: px(wrapperHeight * scale),
188
- ...rounded && { borderRadius: px(12) },
189
- ...style,
190
- ...styleGroups?.wrapper
191
- },
232
+ className,
233
+ style,
234
+ classNames: classGroups,
235
+ styles: { wrapper: styleGroups?.wrapper, inner: innerStyle },
236
+ rounded,
237
+ scale,
238
+ orientation,
192
239
  ...props,
193
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
194
- "div",
195
- {
196
- className: classGroups?.inner,
197
- style: {
198
- width: px(innerWidth),
199
- height: px(innerHeight),
200
- borderWidth: px(12),
201
- ...innerStyle
202
- },
203
- children
204
- }
205
- )
240
+ children
206
241
  }
207
242
  );
208
243
  });
@@ -504,8 +539,9 @@ var Watermark = (0, import_react2.memo)(({ children: watermark, className, style
504
539
  });
505
540
 
506
541
  // src/cardtypes/character.tsx
542
+ var import_react3 = require("react");
507
543
  var import_jsx_runtime4 = require("react/jsx-runtime");
508
- var Character = ({ card, scale, orientation, rounded, className, style, ...props }) => {
544
+ var Character = (0, import_react3.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
509
545
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
510
546
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexGrow: 1 }, children: [
511
547
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", position: "relative", flexDirection: "column", width: px(35) }, children: [
@@ -544,12 +580,13 @@ var Character = ({ card, scale, orientation, rounded, className, style, ...props
544
580
  ] })
545
581
  ] })
546
582
  ] });
547
- };
583
+ });
548
584
  var character_default = Character;
549
585
 
550
586
  // src/cardtypes/location.tsx
587
+ var import_react4 = require("react");
551
588
  var import_jsx_runtime5 = require("react/jsx-runtime");
552
- var Location = ({ card, scale, orientation, rounded, className, style, ...props }) => {
589
+ var Location = (0, import_react4.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
553
590
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "row" } }, style, ...props, children: [
554
591
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", display: "flex", flexDirection: "column", width: px(35) }, children: [
555
592
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Cost, { children: card.cost }),
@@ -583,12 +620,13 @@ var Location = ({ card, scale, orientation, rounded, className, style, ...props
583
620
  ] })
584
621
  ] })
585
622
  ] });
586
- };
623
+ });
587
624
  var location_default = Location;
588
625
 
589
626
  // src/cardtypes/attachment.tsx
627
+ var import_react5 = require("react");
590
628
  var import_jsx_runtime6 = require("react/jsx-runtime");
591
- var Attachment = ({ card, scale, orientation, rounded, className, style, ...props }) => {
629
+ var Attachment = (0, import_react5.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
592
630
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
593
631
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexGrow: 1 }, children: [
594
632
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", width: px(35) }, children: [
@@ -618,12 +656,13 @@ var Attachment = ({ card, scale, orientation, rounded, className, style, ...prop
618
656
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Faction, { children: card.faction })
619
657
  ] })
620
658
  ] });
621
- };
659
+ });
622
660
  var attachment_default = Attachment;
623
661
 
624
662
  // src/cardtypes/event.tsx
663
+ var import_react6 = require("react");
625
664
  var import_jsx_runtime7 = require("react/jsx-runtime");
626
- var Event = ({ card, scale, orientation, rounded, className, style, ...props }) => {
665
+ var Event = (0, import_react6.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
627
666
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
628
667
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexGrow: 1 }, children: [
629
668
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", width: px(35) }, children: [
@@ -652,12 +691,13 @@ var Event = ({ card, scale, orientation, rounded, className, style, ...props })
652
691
  ] })
653
692
  ] })
654
693
  ] });
655
- };
694
+ });
656
695
  var event_default = Event;
657
696
 
658
697
  // src/cardtypes/plot.tsx
698
+ var import_react7 = require("react");
659
699
  var import_jsx_runtime8 = require("react/jsx-runtime");
660
- var Plot = ({ card, scale, orientation, rounded, className, style, ...props }) => {
700
+ var Plot = (0, import_react7.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
661
701
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Card, { scale, card, orientation, rounded, className, style, ...props, children: [
662
702
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "row", alignItems: "center", height: px(40) }, children: [
663
703
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: px(4), width: px(110) }, children: [
@@ -687,12 +727,13 @@ var Plot = ({ card, scale, orientation, rounded, className, style, ...props }) =
687
727
  ] })
688
728
  ] })
689
729
  ] });
690
- };
730
+ });
691
731
  var plot_default = Plot;
692
732
 
693
733
  // src/cardtypes/agenda.tsx
734
+ var import_react8 = require("react");
694
735
  var import_jsx_runtime9 = require("react/jsx-runtime");
695
- var Agenda = ({ card, scale, orientation, rounded, className, style, ...props }) => {
736
+ var Agenda = (0, import_react8.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
696
737
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
697
738
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
698
739
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Name, { children: card.name }),
@@ -710,14 +751,14 @@ var Agenda = ({ card, scale, orientation, rounded, className, style, ...props })
710
751
  ] })
711
752
  ] })
712
753
  ] });
713
- };
754
+ });
714
755
  var agenda_default = Agenda;
715
756
 
716
757
  // src/index.tsx
717
- var import_react3 = require("react");
758
+ var import_react9 = require("react");
718
759
  var import_jsx_runtime10 = require("react/jsx-runtime");
719
- var CardPreview = ({ card, scale, orientation, rounded, className, style, ...props }) => {
720
- const CardComponent = (0, import_react3.useMemo)(() => {
760
+ var CardPreview = (0, import_react9.memo)(({ card, scale, orientation, rounded, className, style, ...props }) => {
761
+ const CardComponent = (0, import_react9.useMemo)(() => {
721
762
  switch (card.type) {
722
763
  case "character":
723
764
  return character_default;
@@ -736,5 +777,10 @@ var CardPreview = ({ card, scale, orientation, rounded, className, style, ...pro
736
777
  }
737
778
  }, [card.type]);
738
779
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CardComponent, { card, scale, orientation, rounded, className, style, ...props });
739
- };
740
- var index_default = CardPreview;
780
+ });
781
+ var CardBlank = CardWrapper;
782
+ // Annotate the CommonJS export names for ESM import in node:
783
+ 0 && (module.exports = {
784
+ CardBlank,
785
+ CardPreview
786
+ });
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/cardComponents.tsx
2
- import classNames2 from "classnames";
2
+ import classNames from "classnames";
3
3
 
4
4
  // ../common/models/cards.ts
5
5
  var challengeIcons = ["military", "intrigue", "power"];
@@ -19,6 +19,14 @@ import { useEffect, useRef } from "react";
19
19
  // src/utils.ts
20
20
  var px = (value) => `${value}px`;
21
21
  var em = (value) => `${value}em`;
22
+ var BASE_WIDTH = 240;
23
+ var BASE_HEIGHT = 333;
24
+ var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
25
+ var divisor = gcd(BASE_WIDTH, BASE_HEIGHT);
26
+ var ASPECT_RATIO = {
27
+ width: BASE_WIDTH / divisor,
28
+ height: BASE_HEIGHT / divisor
29
+ };
22
30
 
23
31
  // src/components/autoSize.tsx
24
32
  import { jsx } from "react/jsx-runtime";
@@ -64,10 +72,7 @@ var AutoSize = ({ children, className, style, height, rate = 0.01, minimum = 0.4
64
72
  var autoSize_default = AutoSize;
65
73
 
66
74
  // src/components/cardComponents.tsx
67
- import { memo, useMemo } from "react";
68
-
69
- // ../client/src/components/thronesIcon.tsx
70
- import classNames from "classnames";
75
+ import { memo, useLayoutEffect, useMemo, useRef as useRef2, useState } from "react";
71
76
 
72
77
  // ../common/utils.ts
73
78
  var thronesColors = {
@@ -110,63 +115,92 @@ var thronesIcons = {
110
115
  agenda: "\uE611"
111
116
  };
112
117
 
113
- // ../client/src/components/thronesIcon.tsx
118
+ // src/components/thronesIcon.tsx
114
119
  import { jsx as jsx2 } from "react/jsx-runtime";
115
120
  var ThronesIcon = ({ name, className, style, visible = true }) => {
116
- return /* @__PURE__ */ jsx2("span", { className: classNames("font-thronesdb leading-none", { invisible: !visible, "leading-relaxed": name === "unique" }, className), style, children: thronesIcons[name] });
121
+ return /* @__PURE__ */ jsx2("span", { className, style: {
122
+ fontFamily: "thronesdb",
123
+ ...!visible && { visibility: "hidden" },
124
+ lineHeight: name === "unique" ? 1.625 : 1,
125
+ ...style
126
+ }, children: thronesIcons[name] });
117
127
  };
118
128
  var thronesIcon_default = ThronesIcon;
119
129
 
120
130
  // src/components/cardComponents.tsx
121
131
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
132
+ var CardWrapper = memo(({ children, scale = 1, orientation = "vertical", rounded = false, className, classNames: classGroups, style, styles: styleGroups, ...props }) => {
133
+ const wrapperRef = useRef2(null);
134
+ const [renderedWidth, setRenderedWidth] = useState(BASE_WIDTH * scale);
135
+ useLayoutEffect(() => {
136
+ const element = wrapperRef.current;
137
+ if (!element) return;
138
+ const observer = new ResizeObserver((entries) => {
139
+ for (const entry of entries) {
140
+ const width = entry.contentRect.width;
141
+ if (width > 0) {
142
+ setRenderedWidth(width * scale);
143
+ }
144
+ }
145
+ });
146
+ observer.observe(element);
147
+ return () => observer.disconnect();
148
+ }, [scale]);
149
+ const dynamicScale = useMemo(() => {
150
+ const baseWidth = orientation === "horizontal" ? BASE_HEIGHT : BASE_WIDTH;
151
+ return renderedWidth / baseWidth;
152
+ }, [orientation, renderedWidth]);
153
+ const aspectRatio = useMemo(() => orientation === "horizontal" ? `${ASPECT_RATIO.height}/${ASPECT_RATIO.width}` : `${ASPECT_RATIO.width}/${ASPECT_RATIO.height}`, [orientation]);
154
+ const wrapperStyle = useMemo(() => ({
155
+ overflow: "hidden",
156
+ position: "relative",
157
+ aspectRatio,
158
+ width: "100%",
159
+ height: "100%",
160
+ ...rounded && { borderRadius: px(12 * dynamicScale) },
161
+ ...style,
162
+ ...styleGroups?.wrapper
163
+ }), [aspectRatio, dynamicScale, rounded, style, styleGroups?.wrapper]);
164
+ const innerStyle = useMemo(() => ({
165
+ width: px(BASE_WIDTH),
166
+ height: px(BASE_HEIGHT),
167
+ transform: `scale(${dynamicScale})`,
168
+ transformOrigin: "top left",
169
+ position: "absolute",
170
+ top: 0,
171
+ left: 0,
172
+ ...styleGroups?.inner
173
+ }), [dynamicScale, styleGroups?.inner]);
174
+ return /* @__PURE__ */ jsx3("div", { ref: wrapperRef, className: classNames(className, classGroups?.wrapper), style: wrapperStyle, ...props, children: /* @__PURE__ */ jsx3("div", { className: classGroups?.inner, style: innerStyle, children }) });
175
+ });
122
176
  var defaultOrientation = (type) => type === "plot" ? "horizontal" : "vertical";
123
- var Card = memo(({ children, card, orientation = defaultOrientation(card.type), scale = 1, rounded = true, className, classNames: classGroups, style, styles: styleGroups, ...props }) => {
124
- const width = 240;
125
- const height = 333;
126
- const wrapperWidth = orientation === "horizontal" ? height : width;
127
- const wrapperHeight = orientation === "horizontal" ? width : height;
128
- const innerWidth = card.type === "plot" ? height : width;
129
- const innerHeight = card.type === "plot" ? width : height;
130
- const rotate = orientation !== defaultOrientation(card.type);
131
- const innerStyle = useMemo(() => {
132
- const style2 = {
133
- borderColor: card.faction ? thronesColors[card.faction] : "white",
134
- background: "white",
135
- color: "black",
136
- fontFamily: "Open Sans, sans-serif",
137
- ...scale !== 1 && { scale },
138
- ...(scale !== 1 || rotate) && { transformOrigin: "top left" },
139
- ...rotate && { position: "relative", rotate: "270deg", top: "100%" },
140
- ...styleGroups?.inner
141
- };
142
- return style2;
143
- }, [card.faction, rotate, scale, styleGroups?.inner]);
177
+ var Card = memo(({ children, card, orientation = defaultOrientation(card.type), rounded = true, scale = 1, className, classNames: classGroups, style, styles: styleGroups, ...props }) => {
178
+ const innerWidth = card.type === "plot" ? BASE_HEIGHT : BASE_WIDTH;
179
+ const innerHeight = card.type === "plot" ? BASE_WIDTH : BASE_HEIGHT;
180
+ const rotated = orientation !== defaultOrientation(card.type);
181
+ const innerStyle = useMemo(() => ({
182
+ width: px(innerWidth),
183
+ height: px(innerHeight),
184
+ borderWidth: px(12),
185
+ borderColor: card.faction ? thronesColors[card.faction] : "white",
186
+ background: "white",
187
+ color: "black",
188
+ fontFamily: "Open Sans, sans-serif",
189
+ ...rotated && { rotate: "270deg", top: "100%" },
190
+ ...styleGroups?.inner
191
+ }), [card.faction, innerHeight, innerWidth, rotated, styleGroups?.inner]);
144
192
  return /* @__PURE__ */ jsx3(
145
- "div",
193
+ CardWrapper,
146
194
  {
147
- className: classNames2(className, classGroups?.wrapper),
148
- style: {
149
- overflow: "hidden",
150
- width: px(wrapperWidth * scale),
151
- height: px(wrapperHeight * scale),
152
- ...rounded && { borderRadius: px(12) },
153
- ...style,
154
- ...styleGroups?.wrapper
155
- },
195
+ className,
196
+ style,
197
+ classNames: classGroups,
198
+ styles: { wrapper: styleGroups?.wrapper, inner: innerStyle },
199
+ rounded,
200
+ scale,
201
+ orientation,
156
202
  ...props,
157
- children: /* @__PURE__ */ jsx3(
158
- "div",
159
- {
160
- className: classGroups?.inner,
161
- style: {
162
- width: px(innerWidth),
163
- height: px(innerHeight),
164
- borderWidth: px(12),
165
- ...innerStyle
166
- },
167
- children
168
- }
169
- )
203
+ children
170
204
  }
171
205
  );
172
206
  });
@@ -468,8 +502,9 @@ var Watermark = memo(({ children: watermark, className, style }) => {
468
502
  });
469
503
 
470
504
  // src/cardtypes/character.tsx
505
+ import { memo as memo2 } from "react";
471
506
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
472
- var Character = ({ card, scale, orientation, rounded, className, style, ...props }) => {
507
+ var Character = memo2(({ card, scale, orientation, rounded, className, style, ...props }) => {
473
508
  return /* @__PURE__ */ jsxs2(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
474
509
  /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexGrow: 1 }, children: [
475
510
  /* @__PURE__ */ jsxs2("div", { style: { display: "flex", position: "relative", flexDirection: "column", width: px(35) }, children: [
@@ -508,12 +543,13 @@ var Character = ({ card, scale, orientation, rounded, className, style, ...props
508
543
  ] })
509
544
  ] })
510
545
  ] });
511
- };
546
+ });
512
547
  var character_default = Character;
513
548
 
514
549
  // src/cardtypes/location.tsx
550
+ import { memo as memo3 } from "react";
515
551
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
516
- var Location = ({ card, scale, orientation, rounded, className, style, ...props }) => {
552
+ var Location = memo3(({ card, scale, orientation, rounded, className, style, ...props }) => {
517
553
  return /* @__PURE__ */ jsxs3(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "row" } }, style, ...props, children: [
518
554
  /* @__PURE__ */ jsxs3("div", { style: { position: "relative", display: "flex", flexDirection: "column", width: px(35) }, children: [
519
555
  /* @__PURE__ */ jsx5(Cost, { children: card.cost }),
@@ -547,12 +583,13 @@ var Location = ({ card, scale, orientation, rounded, className, style, ...props
547
583
  ] })
548
584
  ] })
549
585
  ] });
550
- };
586
+ });
551
587
  var location_default = Location;
552
588
 
553
589
  // src/cardtypes/attachment.tsx
590
+ import { memo as memo4 } from "react";
554
591
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
555
- var Attachment = ({ card, scale, orientation, rounded, className, style, ...props }) => {
592
+ var Attachment = memo4(({ card, scale, orientation, rounded, className, style, ...props }) => {
556
593
  return /* @__PURE__ */ jsxs4(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
557
594
  /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexGrow: 1 }, children: [
558
595
  /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", width: px(35) }, children: [
@@ -582,12 +619,13 @@ var Attachment = ({ card, scale, orientation, rounded, className, style, ...prop
582
619
  /* @__PURE__ */ jsx6(Faction, { children: card.faction })
583
620
  ] })
584
621
  ] });
585
- };
622
+ });
586
623
  var attachment_default = Attachment;
587
624
 
588
625
  // src/cardtypes/event.tsx
626
+ import { memo as memo5 } from "react";
589
627
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
590
- var Event = ({ card, scale, orientation, rounded, className, style, ...props }) => {
628
+ var Event = memo5(({ card, scale, orientation, rounded, className, style, ...props }) => {
591
629
  return /* @__PURE__ */ jsxs5(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
592
630
  /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexGrow: 1 }, children: [
593
631
  /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", width: px(35) }, children: [
@@ -616,12 +654,13 @@ var Event = ({ card, scale, orientation, rounded, className, style, ...props })
616
654
  ] })
617
655
  ] })
618
656
  ] });
619
- };
657
+ });
620
658
  var event_default = Event;
621
659
 
622
660
  // src/cardtypes/plot.tsx
661
+ import { memo as memo6 } from "react";
623
662
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
624
- var Plot = ({ card, scale, orientation, rounded, className, style, ...props }) => {
663
+ var Plot = memo6(({ card, scale, orientation, rounded, className, style, ...props }) => {
625
664
  return /* @__PURE__ */ jsxs6(Card, { scale, card, orientation, rounded, className, style, ...props, children: [
626
665
  /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "row", alignItems: "center", height: px(40) }, children: [
627
666
  /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: px(4), width: px(110) }, children: [
@@ -651,12 +690,13 @@ var Plot = ({ card, scale, orientation, rounded, className, style, ...props }) =
651
690
  ] })
652
691
  ] })
653
692
  ] });
654
- };
693
+ });
655
694
  var plot_default = Plot;
656
695
 
657
696
  // src/cardtypes/agenda.tsx
697
+ import { memo as memo7 } from "react";
658
698
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
659
- var Agenda = ({ card, scale, orientation, rounded, className, style, ...props }) => {
699
+ var Agenda = memo7(({ card, scale, orientation, rounded, className, style, ...props }) => {
660
700
  return /* @__PURE__ */ jsxs7(Card, { scale, card, orientation, rounded, className, styles: { inner: { display: "flex", flexDirection: "column" } }, style, ...props, children: [
661
701
  /* @__PURE__ */ jsxs7("div", { children: [
662
702
  /* @__PURE__ */ jsx9(Name, { children: card.name }),
@@ -674,13 +714,13 @@ var Agenda = ({ card, scale, orientation, rounded, className, style, ...props })
674
714
  ] })
675
715
  ] })
676
716
  ] });
677
- };
717
+ });
678
718
  var agenda_default = Agenda;
679
719
 
680
720
  // src/index.tsx
681
- import { useMemo as useMemo2 } from "react";
721
+ import { memo as memo8, useMemo as useMemo2 } from "react";
682
722
  import { jsx as jsx10 } from "react/jsx-runtime";
683
- var CardPreview = ({ card, scale, orientation, rounded, className, style, ...props }) => {
723
+ var CardPreview = memo8(({ card, scale, orientation, rounded, className, style, ...props }) => {
684
724
  const CardComponent = useMemo2(() => {
685
725
  switch (card.type) {
686
726
  case "character":
@@ -700,8 +740,9 @@ var CardPreview = ({ card, scale, orientation, rounded, className, style, ...pro
700
740
  }
701
741
  }, [card.type]);
702
742
  return /* @__PURE__ */ jsx10(CardComponent, { card, scale, orientation, rounded, className, style, ...props });
703
- };
704
- var index_default = CardPreview;
743
+ });
744
+ var CardBlank = CardWrapper;
705
745
  export {
706
- index_default as default
746
+ CardBlank,
747
+ CardPreview
707
748
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agot/card-preview",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "author": "Stephen Patane",
5
5
  "license": "ISC",
6
6
  "description": "A React component library for rendering \"A Game of Thrones LCG 2nd Edition\" cards.",
@@ -13,6 +13,7 @@
13
13
  "types": "dist/index.d.ts",
14
14
  "scripts": {
15
15
  "build": "tsup src/index.tsx --format esm,cjs --dts --out-dir dist --clean",
16
+ "watch": "tsup src/index.tsx --format esm,cjs --dts --out-dir dist --clean --watch",
16
17
  "prepublishOnly": "npm run build"
17
18
  },
18
19
  "keywords": [],