@ankhorage/zora-tabletop 0.0.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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/dist/cardLabel.d.ts +4 -0
  4. package/dist/cardLabel.d.ts.map +1 -0
  5. package/dist/cardLabel.js +9 -0
  6. package/dist/cardLabel.js.map +1 -0
  7. package/dist/cardSizing.d.ts +10 -0
  8. package/dist/cardSizing.d.ts.map +1 -0
  9. package/dist/cardSizing.js +27 -0
  10. package/dist/cardSizing.js.map +1 -0
  11. package/dist/colors.d.ts +44 -0
  12. package/dist/colors.d.ts.map +1 -0
  13. package/dist/colors.js +20 -0
  14. package/dist/colors.js.map +1 -0
  15. package/dist/components/card-back/CardBack.d.ts +4 -0
  16. package/dist/components/card-back/CardBack.d.ts.map +1 -0
  17. package/dist/components/card-back/CardBack.js +44 -0
  18. package/dist/components/card-back/CardBack.js.map +1 -0
  19. package/dist/components/card-back/index.d.ts +3 -0
  20. package/dist/components/card-back/index.d.ts.map +1 -0
  21. package/dist/components/card-back/index.js +2 -0
  22. package/dist/components/card-back/index.js.map +1 -0
  23. package/dist/components/card-back/types.d.ts +10 -0
  24. package/dist/components/card-back/types.d.ts.map +1 -0
  25. package/dist/components/card-back/types.js +2 -0
  26. package/dist/components/card-back/types.js.map +1 -0
  27. package/dist/components/card-hand/CardHand.d.ts +4 -0
  28. package/dist/components/card-hand/CardHand.d.ts.map +1 -0
  29. package/dist/components/card-hand/CardHand.js +23 -0
  30. package/dist/components/card-hand/CardHand.js.map +1 -0
  31. package/dist/components/card-hand/index.d.ts +3 -0
  32. package/dist/components/card-hand/index.d.ts.map +1 -0
  33. package/dist/components/card-hand/index.js +2 -0
  34. package/dist/components/card-hand/index.js.map +1 -0
  35. package/dist/components/card-hand/types.d.ts +12 -0
  36. package/dist/components/card-hand/types.d.ts.map +1 -0
  37. package/dist/components/card-hand/types.js +2 -0
  38. package/dist/components/card-hand/types.js.map +1 -0
  39. package/dist/components/playing-card/PlayingCard.d.ts +4 -0
  40. package/dist/components/playing-card/PlayingCard.d.ts.map +1 -0
  41. package/dist/components/playing-card/PlayingCard.js +68 -0
  42. package/dist/components/playing-card/PlayingCard.js.map +1 -0
  43. package/dist/components/playing-card/index.d.ts +3 -0
  44. package/dist/components/playing-card/index.d.ts.map +1 -0
  45. package/dist/components/playing-card/index.js +2 -0
  46. package/dist/components/playing-card/index.js.map +1 -0
  47. package/dist/components/playing-card/types.d.ts +12 -0
  48. package/dist/components/playing-card/types.d.ts.map +1 -0
  49. package/dist/components/playing-card/types.js +2 -0
  50. package/dist/components/playing-card/types.js.map +1 -0
  51. package/dist/components/tabletop-table/TabletopTable.d.ts +4 -0
  52. package/dist/components/tabletop-table/TabletopTable.d.ts.map +1 -0
  53. package/dist/components/tabletop-table/TabletopTable.js +165 -0
  54. package/dist/components/tabletop-table/TabletopTable.js.map +1 -0
  55. package/dist/components/tabletop-table/index.d.ts +3 -0
  56. package/dist/components/tabletop-table/index.d.ts.map +1 -0
  57. package/dist/components/tabletop-table/index.js +2 -0
  58. package/dist/components/tabletop-table/index.js.map +1 -0
  59. package/dist/components/tabletop-table/types.d.ts +17 -0
  60. package/dist/components/tabletop-table/types.d.ts.map +1 -0
  61. package/dist/components/tabletop-table/types.js +2 -0
  62. package/dist/components/tabletop-table/types.js.map +1 -0
  63. package/dist/index.d.ts +12 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +6 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/tablePositions.d.ts +11 -0
  68. package/dist/tablePositions.d.ts.map +1 -0
  69. package/dist/tablePositions.js +85 -0
  70. package/dist/tablePositions.js.map +1 -0
  71. package/dist/types.d.ts +22 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +2 -0
  74. package/dist/types.js.map +1 -0
  75. package/package.json +82 -0
  76. package/src/cardLabel.ts +11 -0
  77. package/src/cardSizing.ts +37 -0
  78. package/src/colors.ts +67 -0
  79. package/src/components/card-back/CardBack.tsx +66 -0
  80. package/src/components/card-back/index.ts +2 -0
  81. package/src/components/card-back/types.ts +10 -0
  82. package/src/components/card-hand/CardHand.tsx +55 -0
  83. package/src/components/card-hand/index.ts +2 -0
  84. package/src/components/card-hand/types.ts +12 -0
  85. package/src/components/playing-card/PlayingCard.tsx +99 -0
  86. package/src/components/playing-card/index.ts +2 -0
  87. package/src/components/playing-card/types.ts +12 -0
  88. package/src/components/tabletop-table/TabletopTable.tsx +219 -0
  89. package/src/components/tabletop-table/index.ts +2 -0
  90. package/src/components/tabletop-table/types.ts +24 -0
  91. package/src/index.ts +18 -0
  92. package/src/tablePositions.test.ts +40 -0
  93. package/src/tablePositions.ts +97 -0
  94. package/src/types.ts +24 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabletopTable.d.ts","sourceRoot":"","sources":["../../../src/components/tabletop-table/TabletopTable.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAelD,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAgB,EAChB,WAAW,EACX,cAAc,EACd,KAAc,EACd,SAAS,EACT,QAAkB,EAClB,QAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,MAAM,GACP,EAAE,kBAAkB,qBAmGpB"}
@@ -0,0 +1,165 @@
1
+ import { useZoraTheme } from '@ankhorage/zora';
2
+ import React from 'react';
3
+ import { StyleSheet, Text, View } from 'react-native';
4
+ import { createTabletopColorScheme } from '../../colors';
5
+ import { getTabletopSeatPosition } from '../../tablePositions';
6
+ import { CardHand } from '../card-hand';
7
+ function createSeatAccessibilityLabel(seat) {
8
+ if (seat.accessibilityLabel !== undefined)
9
+ return seat.accessibilityLabel;
10
+ if (typeof seat.label !== 'string')
11
+ return undefined;
12
+ const parts = [seat.label];
13
+ if (typeof seat.sublabel === 'string')
14
+ parts.push(seat.sublabel);
15
+ if (typeof seat.tokenLabel === 'string')
16
+ parts.push(seat.tokenLabel);
17
+ if (seat.selected)
18
+ parts.push('selected');
19
+ if (seat.muted)
20
+ parts.push('muted');
21
+ return parts.join(', ');
22
+ }
23
+ export function TabletopTable({ seats, centerCards = [], centerLabel, centerSublabel, shape = 'oval', seatCount, cardSize = 'small', disabled = false, colorScheme, accessibilityLabel, testID, }) {
24
+ const { theme } = useZoraTheme();
25
+ const colors = React.useMemo(() => createTabletopColorScheme(theme, colorScheme), [colorScheme, theme]);
26
+ const resolvedSeatCount = seatCount ?? seats.length;
27
+ return (<View accessibilityLabel={accessibilityLabel} style={[styles.root, { opacity: disabled ? 0.56 : 1 }]} testID={testID}>
28
+ <View style={[
29
+ styles.surface,
30
+ shape === 'circle' ? styles.circleSurface : styles.ovalSurface,
31
+ shape === 'rounded' ? styles.roundedSurface : null,
32
+ {
33
+ backgroundColor: colors.tableFelt,
34
+ borderColor: colors.tableBorder,
35
+ },
36
+ ]}>
37
+ <View pointerEvents="none" style={[
38
+ styles.innerSurface,
39
+ shape === 'circle' ? styles.circleSurface : styles.ovalSurface,
40
+ shape === 'rounded' ? styles.roundedSurface : null,
41
+ { borderColor: colors.tableInnerBorder },
42
+ ]}/>
43
+ <View style={styles.centerContent}>
44
+ {centerCards.length > 0 ? (<CardHand cards={centerCards} colorScheme={colorScheme} size={cardSize}/>) : null}
45
+ {centerLabel !== undefined ? (<View style={[styles.centerLabel, { backgroundColor: colors.seatSurface }]}>
46
+ <Text style={[styles.centerLabelText, { color: colors.cardText }]}>
47
+ {centerLabel}
48
+ </Text>
49
+ </View>) : null}
50
+ {centerSublabel !== undefined ? (<Text style={[styles.centerSublabel, { color: colors.mutedText }]}>
51
+ {centerSublabel}
52
+ </Text>) : null}
53
+ </View>
54
+ </View>
55
+
56
+ {seats.map((seat, index) => {
57
+ const position = getTabletopSeatPosition(index, resolvedSeatCount);
58
+ return (<View accessibilityLabel={createSeatAccessibilityLabel(seat)} accessibilityRole="summary" key={seat.id} style={[
59
+ styles.seat,
60
+ {
61
+ borderColor: seat.selected ? colors.seatSelectedBorder : colors.seatBorder,
62
+ backgroundColor: colors.seatSurface,
63
+ left: position.left,
64
+ opacity: seat.muted ? 0.48 : 1,
65
+ top: position.top,
66
+ },
67
+ ]} testID={testID ? `${testID}-seat-${seat.id}` : undefined}>
68
+ {seat.cards !== undefined || seat.faceDownCards !== undefined ? (<CardHand cards={seat.cards} colorScheme={colorScheme} faceDownCards={seat.faceDownCards} muted={seat.muted ?? seat.disabled} size={cardSize}/>) : null}
69
+ <Text style={[styles.seatLabel, { color: colors.cardText }]}>{seat.label}</Text>
70
+ {seat.sublabel !== undefined ? (<Text style={[styles.seatSublabel, { color: colors.mutedText }]}>
71
+ {seat.sublabel}
72
+ </Text>) : null}
73
+ {seat.tokenLabel !== undefined ? (<View style={[styles.token, { backgroundColor: colors.tokenSurface }]}>
74
+ <Text style={[styles.tokenText, { color: colors.tokenText }]}>
75
+ {seat.tokenLabel}
76
+ </Text>
77
+ </View>) : null}
78
+ </View>);
79
+ })}
80
+ </View>);
81
+ }
82
+ const styles = StyleSheet.create({
83
+ centerContent: {
84
+ alignItems: 'center',
85
+ gap: 6,
86
+ left: 0,
87
+ position: 'absolute',
88
+ right: 0,
89
+ top: '35%',
90
+ },
91
+ centerLabel: {
92
+ borderRadius: 999,
93
+ paddingHorizontal: 10,
94
+ paddingVertical: 4,
95
+ },
96
+ centerLabelText: {
97
+ fontSize: 12,
98
+ fontWeight: '800',
99
+ },
100
+ centerSublabel: {
101
+ fontSize: 11,
102
+ fontWeight: '600',
103
+ },
104
+ circleSurface: {
105
+ borderRadius: 999,
106
+ },
107
+ innerSurface: {
108
+ borderWidth: 1,
109
+ bottom: 10,
110
+ left: 10,
111
+ opacity: 0.44,
112
+ position: 'absolute',
113
+ right: 10,
114
+ top: 10,
115
+ },
116
+ ovalSurface: {
117
+ borderRadius: 999,
118
+ },
119
+ root: {
120
+ aspectRatio: 1.6,
121
+ maxWidth: 760,
122
+ position: 'relative',
123
+ width: '100%',
124
+ },
125
+ roundedSurface: {
126
+ borderRadius: 28,
127
+ },
128
+ seat: {
129
+ alignItems: 'center',
130
+ borderRadius: 10,
131
+ borderWidth: 1,
132
+ gap: 3,
133
+ minWidth: 64,
134
+ paddingHorizontal: 6,
135
+ paddingVertical: 5,
136
+ position: 'absolute',
137
+ transform: [{ translateX: -32 }, { translateY: -28 }],
138
+ },
139
+ seatLabel: {
140
+ fontSize: 11,
141
+ fontWeight: '800',
142
+ },
143
+ seatSublabel: {
144
+ fontSize: 10,
145
+ fontWeight: '600',
146
+ },
147
+ surface: {
148
+ borderWidth: 8,
149
+ bottom: 28,
150
+ left: 24,
151
+ position: 'absolute',
152
+ right: 24,
153
+ top: 24,
154
+ },
155
+ token: {
156
+ borderRadius: 999,
157
+ paddingHorizontal: 6,
158
+ paddingVertical: 2,
159
+ },
160
+ tokenText: {
161
+ fontSize: 10,
162
+ fontWeight: '800',
163
+ },
164
+ });
165
+ //# sourceMappingURL=TabletopTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabletopTable.js","sourceRoot":"","sources":["../../../src/components/tabletop-table/TabletopTable.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useZoraTheme } from '@ankhorage/zora';\nimport React from 'react';\nimport { StyleSheet, Text, View } from 'react-native';\n\nimport { createTabletopColorScheme } from '../../colors';\nimport { getTabletopSeatPosition } from '../../tablePositions';\nimport type { TabletopSeatState } from '../../types';\nimport { CardHand } from '../card-hand';\nimport type { TabletopTableProps } from './types';\n\nfunction createSeatAccessibilityLabel(seat: TabletopSeatState): string | undefined {\n if (seat.accessibilityLabel !== undefined) return seat.accessibilityLabel;\n if (typeof seat.label !== 'string') return undefined;\n\n const parts = [seat.label];\n if (typeof seat.sublabel === 'string') parts.push(seat.sublabel);\n if (typeof seat.tokenLabel === 'string') parts.push(seat.tokenLabel);\n if (seat.selected) parts.push('selected');\n if (seat.muted) parts.push('muted');\n\n return parts.join(', ');\n}\n\nexport function TabletopTable({\n seats,\n centerCards = [],\n centerLabel,\n centerSublabel,\n shape = 'oval',\n seatCount,\n cardSize = 'small',\n disabled = false,\n colorScheme,\n accessibilityLabel,\n testID,\n}: TabletopTableProps) {\n const { theme } = useZoraTheme();\n const colors = React.useMemo(\n () => createTabletopColorScheme(theme, colorScheme),\n [colorScheme, theme],\n );\n const resolvedSeatCount = seatCount ?? seats.length;\n\n return (\n <View\n accessibilityLabel={accessibilityLabel}\n style={[styles.root, { opacity: disabled ? 0.56 : 1 }]}\n testID={testID}\n >\n <View\n style={[\n styles.surface,\n shape === 'circle' ? styles.circleSurface : styles.ovalSurface,\n shape === 'rounded' ? styles.roundedSurface : null,\n {\n backgroundColor: colors.tableFelt,\n borderColor: colors.tableBorder,\n },\n ]}\n >\n <View\n pointerEvents=\"none\"\n style={[\n styles.innerSurface,\n shape === 'circle' ? styles.circleSurface : styles.ovalSurface,\n shape === 'rounded' ? styles.roundedSurface : null,\n { borderColor: colors.tableInnerBorder },\n ]}\n />\n <View style={styles.centerContent}>\n {centerCards.length > 0 ? (\n <CardHand cards={centerCards} colorScheme={colorScheme} size={cardSize} />\n ) : null}\n {centerLabel !== undefined ? (\n <View style={[styles.centerLabel, { backgroundColor: colors.seatSurface }]}>\n <Text style={[styles.centerLabelText, { color: colors.cardText }]}>\n {centerLabel}\n </Text>\n </View>\n ) : null}\n {centerSublabel !== undefined ? (\n <Text style={[styles.centerSublabel, { color: colors.mutedText }]}>\n {centerSublabel}\n </Text>\n ) : null}\n </View>\n </View>\n\n {seats.map((seat, index) => {\n const position = getTabletopSeatPosition(index, resolvedSeatCount);\n return (\n <View\n accessibilityLabel={createSeatAccessibilityLabel(seat)}\n accessibilityRole=\"summary\"\n key={seat.id}\n style={[\n styles.seat,\n {\n borderColor: seat.selected ? colors.seatSelectedBorder : colors.seatBorder,\n backgroundColor: colors.seatSurface,\n left: position.left,\n opacity: seat.muted ? 0.48 : 1,\n top: position.top,\n },\n ]}\n testID={testID ? `${testID}-seat-${seat.id}` : undefined}\n >\n {seat.cards !== undefined || seat.faceDownCards !== undefined ? (\n <CardHand\n cards={seat.cards}\n colorScheme={colorScheme}\n faceDownCards={seat.faceDownCards}\n muted={seat.muted ?? seat.disabled}\n size={cardSize}\n />\n ) : null}\n <Text style={[styles.seatLabel, { color: colors.cardText }]}>{seat.label}</Text>\n {seat.sublabel !== undefined ? (\n <Text style={[styles.seatSublabel, { color: colors.mutedText }]}>\n {seat.sublabel}\n </Text>\n ) : null}\n {seat.tokenLabel !== undefined ? (\n <View style={[styles.token, { backgroundColor: colors.tokenSurface }]}>\n <Text style={[styles.tokenText, { color: colors.tokenText }]}>\n {seat.tokenLabel}\n </Text>\n </View>\n ) : null}\n </View>\n );\n })}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n centerContent: {\n alignItems: 'center',\n gap: 6,\n left: 0,\n position: 'absolute',\n right: 0,\n top: '35%',\n },\n centerLabel: {\n borderRadius: 999,\n paddingHorizontal: 10,\n paddingVertical: 4,\n },\n centerLabelText: {\n fontSize: 12,\n fontWeight: '800',\n },\n centerSublabel: {\n fontSize: 11,\n fontWeight: '600',\n },\n circleSurface: {\n borderRadius: 999,\n },\n innerSurface: {\n borderWidth: 1,\n bottom: 10,\n left: 10,\n opacity: 0.44,\n position: 'absolute',\n right: 10,\n top: 10,\n },\n ovalSurface: {\n borderRadius: 999,\n },\n root: {\n aspectRatio: 1.6,\n maxWidth: 760,\n position: 'relative',\n width: '100%',\n },\n roundedSurface: {\n borderRadius: 28,\n },\n seat: {\n alignItems: 'center',\n borderRadius: 10,\n borderWidth: 1,\n gap: 3,\n minWidth: 64,\n paddingHorizontal: 6,\n paddingVertical: 5,\n position: 'absolute',\n transform: [{ translateX: -32 }, { translateY: -28 }],\n },\n seatLabel: {\n fontSize: 11,\n fontWeight: '800',\n },\n seatSublabel: {\n fontSize: 10,\n fontWeight: '600',\n },\n surface: {\n borderWidth: 8,\n bottom: 28,\n left: 24,\n position: 'absolute',\n right: 24,\n top: 24,\n },\n token: {\n borderRadius: 999,\n paddingHorizontal: 6,\n paddingVertical: 2,\n },\n tokenText: {\n fontSize: 10,\n fontWeight: '800',\n },\n});\n"]}
@@ -0,0 +1,3 @@
1
+ export { TabletopTable } from './TabletopTable';
2
+ export type { TabletopTableProps } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/tabletop-table/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { TabletopTable } from './TabletopTable';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/tabletop-table/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export { TabletopTable } from './TabletopTable';\nexport type { TabletopTableProps } from './types';\n"]}
@@ -0,0 +1,17 @@
1
+ import type React from 'react';
2
+ import type { TabletopColorOverrides } from '../../colors';
3
+ import type { PlayingCardValue, TabletopCardSize, TabletopSeatCount, TabletopSeatState, TabletopShape } from '../../types';
4
+ export interface TabletopTableProps {
5
+ readonly seats: readonly TabletopSeatState[];
6
+ readonly centerCards?: readonly PlayingCardValue[];
7
+ readonly centerLabel?: React.ReactNode;
8
+ readonly centerSublabel?: React.ReactNode;
9
+ readonly shape?: TabletopShape;
10
+ readonly seatCount?: TabletopSeatCount;
11
+ readonly cardSize?: TabletopCardSize;
12
+ readonly disabled?: boolean;
13
+ readonly colorScheme?: TabletopColorOverrides;
14
+ readonly accessibilityLabel?: string;
15
+ readonly testID?: string;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/tabletop-table/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACd,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvC,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,sBAAsB,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/tabletop-table/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nimport type { TabletopColorOverrides } from '../../colors';\nimport type {\n PlayingCardValue,\n TabletopCardSize,\n TabletopSeatCount,\n TabletopSeatState,\n TabletopShape,\n} from '../../types';\n\nexport interface TabletopTableProps {\n readonly seats: readonly TabletopSeatState[];\n readonly centerCards?: readonly PlayingCardValue[];\n readonly centerLabel?: React.ReactNode;\n readonly centerSublabel?: React.ReactNode;\n readonly shape?: TabletopShape;\n readonly seatCount?: TabletopSeatCount;\n readonly cardSize?: TabletopCardSize;\n readonly disabled?: boolean;\n readonly colorScheme?: TabletopColorOverrides;\n readonly accessibilityLabel?: string;\n readonly testID?: string;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ export type { TabletopColorOverrides, TabletopColorScheme } from './colors';
2
+ export { createTabletopColorScheme } from './colors';
3
+ export type { CardBackProps } from './components/card-back';
4
+ export { CardBack } from './components/card-back';
5
+ export type { CardHandProps } from './components/card-hand';
6
+ export { CardHand } from './components/card-hand';
7
+ export type { PlayingCardProps } from './components/playing-card';
8
+ export { PlayingCard } from './components/playing-card';
9
+ export type { TabletopTableProps } from './components/tabletop-table';
10
+ export { TabletopTable } from './components/tabletop-table';
11
+ export type { PlayingCardSuit, PlayingCardValue, TabletopCardSize, TabletopSeatCount, TabletopSeatState, TabletopShape, } from './types';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { createTabletopColorScheme } from './colors';
2
+ export { CardBack } from './components/card-back';
3
+ export { CardHand } from './components/card-hand';
4
+ export { PlayingCard } from './components/playing-card';
5
+ export { TabletopTable } from './components/tabletop-table';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC","sourcesContent":["export type { TabletopColorOverrides, TabletopColorScheme } from './colors';\nexport { createTabletopColorScheme } from './colors';\nexport type { CardBackProps } from './components/card-back';\nexport { CardBack } from './components/card-back';\nexport type { CardHandProps } from './components/card-hand';\nexport { CardHand } from './components/card-hand';\nexport type { PlayingCardProps } from './components/playing-card';\nexport { PlayingCard } from './components/playing-card';\nexport type { TabletopTableProps } from './components/tabletop-table';\nexport { TabletopTable } from './components/tabletop-table';\nexport type {\n PlayingCardSuit,\n PlayingCardValue,\n TabletopCardSize,\n TabletopSeatCount,\n TabletopSeatState,\n TabletopShape,\n} from './types';\n"]}
@@ -0,0 +1,11 @@
1
+ import type { TabletopSeatCount } from './types';
2
+ type TabletopSeatPositionValue = `${number}%`;
3
+ export interface TabletopSeatPosition {
4
+ readonly top: TabletopSeatPositionValue;
5
+ readonly left: TabletopSeatPositionValue;
6
+ }
7
+ export declare function normalizeTabletopSeatCount(count: number): TabletopSeatCount;
8
+ export declare function getTabletopSeatPositions(count: number): readonly TabletopSeatPosition[];
9
+ export declare function getTabletopSeatPosition(index: number, count: number): TabletopSeatPosition;
10
+ export {};
11
+ //# sourceMappingURL=tablePositions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tablePositions.d.ts","sourceRoot":"","sources":["../src/tablePositions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,KAAK,yBAAyB,GAAG,GAAG,MAAM,GAAG,CAAC;AAE9C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,EAAE,yBAAyB,CAAC;IACxC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;CAC1C;AAwED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAM3E;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAEvF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAK1F"}
@@ -0,0 +1,85 @@
1
+ const fallbackSeatPosition = { top: '82%', left: '50%' };
2
+ const seatPositions = {
3
+ 2: [fallbackSeatPosition, { top: '18%', left: '50%' }],
4
+ 3: [fallbackSeatPosition, { top: '28%', left: '18%' }, { top: '28%', left: '82%' }],
5
+ 4: [
6
+ fallbackSeatPosition,
7
+ { top: '50%', left: '12%' },
8
+ { top: '18%', left: '50%' },
9
+ { top: '50%', left: '88%' },
10
+ ],
11
+ 5: [
12
+ { top: '84%', left: '50%' },
13
+ { top: '62%', left: '12%' },
14
+ { top: '18%', left: '24%' },
15
+ { top: '18%', left: '76%' },
16
+ { top: '62%', left: '88%' },
17
+ ],
18
+ 6: [
19
+ { top: '84%', left: '50%' },
20
+ { top: '68%', left: '16%' },
21
+ { top: '26%', left: '16%' },
22
+ { top: '16%', left: '50%' },
23
+ { top: '26%', left: '84%' },
24
+ { top: '68%', left: '84%' },
25
+ ],
26
+ 7: [
27
+ { top: '86%', left: '50%' },
28
+ { top: '70%', left: '14%' },
29
+ { top: '34%', left: '10%' },
30
+ { top: '14%', left: '34%' },
31
+ { top: '14%', left: '66%' },
32
+ { top: '34%', left: '90%' },
33
+ { top: '70%', left: '86%' },
34
+ ],
35
+ 8: [
36
+ { top: '86%', left: '50%' },
37
+ { top: '72%', left: '16%' },
38
+ { top: '50%', left: '8%' },
39
+ { top: '20%', left: '20%' },
40
+ { top: '14%', left: '50%' },
41
+ { top: '20%', left: '80%' },
42
+ { top: '50%', left: '92%' },
43
+ { top: '72%', left: '84%' },
44
+ ],
45
+ 9: [
46
+ { top: '88%', left: '50%' },
47
+ { top: '78%', left: '12%' },
48
+ { top: '50%', left: '4%' },
49
+ { top: '18%', left: '10%' },
50
+ { top: '8%', left: '28%' },
51
+ { top: '8%', left: '50%' },
52
+ { top: '8%', left: '72%' },
53
+ { top: '18%', left: '90%' },
54
+ { top: '50%', left: '96%' },
55
+ ],
56
+ 10: [
57
+ { top: '88%', left: '50%' },
58
+ { top: '80%', left: '20%' },
59
+ { top: '58%', left: '6%' },
60
+ { top: '30%', left: '8%' },
61
+ { top: '10%', left: '30%' },
62
+ { top: '8%', left: '50%' },
63
+ { top: '10%', left: '70%' },
64
+ { top: '30%', left: '92%' },
65
+ { top: '58%', left: '94%' },
66
+ { top: '80%', left: '80%' },
67
+ ],
68
+ };
69
+ export function normalizeTabletopSeatCount(count) {
70
+ const rounded = Math.round(count);
71
+ if (rounded <= 2)
72
+ return 2;
73
+ if (rounded >= 10)
74
+ return 10;
75
+ return rounded;
76
+ }
77
+ export function getTabletopSeatPositions(count) {
78
+ return seatPositions[normalizeTabletopSeatCount(count)];
79
+ }
80
+ export function getTabletopSeatPosition(index, count) {
81
+ const positions = getTabletopSeatPositions(count);
82
+ const position = positions[index % positions.length];
83
+ return position ?? fallbackSeatPosition;
84
+ }
85
+ //# sourceMappingURL=tablePositions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tablePositions.js","sourceRoot":"","sources":["../src/tablePositions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TabletopSeatCount } from './types';\n\ntype TabletopSeatPositionValue = `${number}%`;\n\nexport interface TabletopSeatPosition {\n readonly top: TabletopSeatPositionValue;\n readonly left: TabletopSeatPositionValue;\n}\n\nconst fallbackSeatPosition: TabletopSeatPosition = { top: '82%', left: '50%' };\n\nconst seatPositions: Readonly<Record<TabletopSeatCount, readonly TabletopSeatPosition[]>> = {\n 2: [fallbackSeatPosition, { top: '18%', left: '50%' }],\n 3: [fallbackSeatPosition, { top: '28%', left: '18%' }, { top: '28%', left: '82%' }],\n 4: [\n fallbackSeatPosition,\n { top: '50%', left: '12%' },\n { top: '18%', left: '50%' },\n { top: '50%', left: '88%' },\n ],\n 5: [\n { top: '84%', left: '50%' },\n { top: '62%', left: '12%' },\n { top: '18%', left: '24%' },\n { top: '18%', left: '76%' },\n { top: '62%', left: '88%' },\n ],\n 6: [\n { top: '84%', left: '50%' },\n { top: '68%', left: '16%' },\n { top: '26%', left: '16%' },\n { top: '16%', left: '50%' },\n { top: '26%', left: '84%' },\n { top: '68%', left: '84%' },\n ],\n 7: [\n { top: '86%', left: '50%' },\n { top: '70%', left: '14%' },\n { top: '34%', left: '10%' },\n { top: '14%', left: '34%' },\n { top: '14%', left: '66%' },\n { top: '34%', left: '90%' },\n { top: '70%', left: '86%' },\n ],\n 8: [\n { top: '86%', left: '50%' },\n { top: '72%', left: '16%' },\n { top: '50%', left: '8%' },\n { top: '20%', left: '20%' },\n { top: '14%', left: '50%' },\n { top: '20%', left: '80%' },\n { top: '50%', left: '92%' },\n { top: '72%', left: '84%' },\n ],\n 9: [\n { top: '88%', left: '50%' },\n { top: '78%', left: '12%' },\n { top: '50%', left: '4%' },\n { top: '18%', left: '10%' },\n { top: '8%', left: '28%' },\n { top: '8%', left: '50%' },\n { top: '8%', left: '72%' },\n { top: '18%', left: '90%' },\n { top: '50%', left: '96%' },\n ],\n 10: [\n { top: '88%', left: '50%' },\n { top: '80%', left: '20%' },\n { top: '58%', left: '6%' },\n { top: '30%', left: '8%' },\n { top: '10%', left: '30%' },\n { top: '8%', left: '50%' },\n { top: '10%', left: '70%' },\n { top: '30%', left: '92%' },\n { top: '58%', left: '94%' },\n { top: '80%', left: '80%' },\n ],\n};\n\nexport function normalizeTabletopSeatCount(count: number): TabletopSeatCount {\n const rounded = Math.round(count);\n if (rounded <= 2) return 2;\n if (rounded >= 10) return 10;\n\n return rounded as TabletopSeatCount;\n}\n\nexport function getTabletopSeatPositions(count: number): readonly TabletopSeatPosition[] {\n return seatPositions[normalizeTabletopSeatCount(count)];\n}\n\nexport function getTabletopSeatPosition(index: number, count: number): TabletopSeatPosition {\n const positions = getTabletopSeatPositions(count);\n const position = positions[index % positions.length];\n\n return position ?? fallbackSeatPosition;\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import type React from 'react';
2
+ export type PlayingCardSuit = 'clubs' | 'diamonds' | 'hearts' | 'spades';
3
+ export type TabletopCardSize = 'large' | 'medium' | 'small';
4
+ export type TabletopShape = 'circle' | 'oval' | 'rounded';
5
+ export type TabletopSeatCount = 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
6
+ export interface PlayingCardValue {
7
+ readonly rank: string;
8
+ readonly suit: PlayingCardSuit;
9
+ }
10
+ export interface TabletopSeatState {
11
+ readonly id: string;
12
+ readonly label: React.ReactNode;
13
+ readonly sublabel?: React.ReactNode;
14
+ readonly cards?: readonly PlayingCardValue[];
15
+ readonly faceDownCards?: number;
16
+ readonly selected?: boolean;
17
+ readonly muted?: boolean;
18
+ readonly disabled?: boolean;
19
+ readonly tokenLabel?: React.ReactNode;
20
+ readonly accessibilityLabel?: string;
21
+ }
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACzE,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC5D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAC1D,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACtC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nexport type PlayingCardSuit = 'clubs' | 'diamonds' | 'hearts' | 'spades';\nexport type TabletopCardSize = 'large' | 'medium' | 'small';\nexport type TabletopShape = 'circle' | 'oval' | 'rounded';\nexport type TabletopSeatCount = 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;\n\nexport interface PlayingCardValue {\n readonly rank: string;\n readonly suit: PlayingCardSuit;\n}\n\nexport interface TabletopSeatState {\n readonly id: string;\n readonly label: React.ReactNode;\n readonly sublabel?: React.ReactNode;\n readonly cards?: readonly PlayingCardValue[];\n readonly faceDownCards?: number;\n readonly selected?: boolean;\n readonly muted?: boolean;\n readonly disabled?: boolean;\n readonly tokenLabel?: React.ReactNode;\n readonly accessibilityLabel?: string;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@ankhorage/zora-tabletop",
3
+ "type": "module",
4
+ "version": "0.0.0",
5
+ "description": "Tabletop and card-game UI primitives for React Native and React Native Web, built on ZORA.",
6
+ "homepage": "https://github.com/ankhorage/zora-tabletop#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/ankhorage/zora-tabletop/issues"
9
+ },
10
+ "license": "MIT",
11
+ "main": "./dist/index.js",
12
+ "sideEffects": false,
13
+ "types": "./dist/index.d.ts",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/ankhorage/zora-tabletop.git"
17
+ },
18
+ "keywords": [
19
+ "react-native",
20
+ "react-native-web",
21
+ "tabletop",
22
+ "cards",
23
+ "card-game",
24
+ "expo",
25
+ "zora",
26
+ "ui-kit"
27
+ ],
28
+ "files": [
29
+ "dist",
30
+ "src",
31
+ "package.json",
32
+ "README.md",
33
+ "CHANGELOG.md",
34
+ "LICENSE"
35
+ ],
36
+ "exports": {
37
+ ".": {
38
+ "react-native": "./src/index.ts",
39
+ "browser": "./src/index.ts",
40
+ "types": "./dist/index.d.ts",
41
+ "import": "./dist/index.js",
42
+ "default": "./dist/index.js"
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "scripts": {
50
+ "build": "rm -rf dist tsconfig.tsbuildinfo && bun x tsc -p tsconfig.json",
51
+ "changeset": "changeset",
52
+ "changeset:status": "changeset status --since=origin/main",
53
+ "docs": "paradox",
54
+ "knip": "ankhorage-knip",
55
+ "lint": "ankhorage-eslint . --max-warnings=0",
56
+ "lint:fix": "ankhorage-eslint . --fix --max-warnings=0",
57
+ "format": "ankhorage-prettier --write .",
58
+ "format:check": "ankhorage-prettier --check .",
59
+ "prepack": "bun run build",
60
+ "test": "bun test src",
61
+ "typecheck": "bun x tsc --noEmit -p tsconfig.json",
62
+ "version-packages": "changeset version"
63
+ },
64
+ "peerDependencies": {
65
+ "@ankhorage/zora": ">=0.1.0",
66
+ "react": ">=18.2.0",
67
+ "react-native": ">=0.72.0"
68
+ },
69
+ "devDependencies": {
70
+ "@ankhorage/devtools": "^1.0.6",
71
+ "@ankhorage/paradox": "^0.1.7",
72
+ "@ankhorage/zora": "^2.5.1",
73
+ "@changesets/cli": "^2.31.0",
74
+ "@types/bun": "^1.3.13",
75
+ "@types/node": "^25.6.0",
76
+ "@types/react": "^19.1.8",
77
+ "react": "^19.1.0",
78
+ "react-native": "^0.81.5",
79
+ "typescript": "^5.9.3"
80
+ },
81
+ "packageManager": "bun@1.3.13"
82
+ }
@@ -0,0 +1,11 @@
1
+ import type { PlayingCardValue } from './types';
2
+
3
+ export function getPlayingCardLabel(card: PlayingCardValue): string {
4
+ return `${card.rank} ${card.suit}`;
5
+ }
6
+
7
+ export function createHiddenCardLabel(index?: number): string {
8
+ if (index === undefined) return 'Hidden card';
9
+
10
+ return `Hidden card ${index + 1}`;
11
+ }
@@ -0,0 +1,37 @@
1
+ import type { TabletopCardSize } from './types';
2
+
3
+ export interface TabletopCardDimensions {
4
+ readonly width: number;
5
+ readonly height: number;
6
+ readonly radius: number;
7
+ readonly rankFontSize: number;
8
+ readonly suitFontSize: number;
9
+ }
10
+
11
+ const cardDimensions: Readonly<Record<TabletopCardSize, TabletopCardDimensions>> = {
12
+ large: {
13
+ width: 56,
14
+ height: 80,
15
+ radius: 8,
16
+ rankFontSize: 20,
17
+ suitFontSize: 16,
18
+ },
19
+ medium: {
20
+ width: 40,
21
+ height: 56,
22
+ radius: 6,
23
+ rankFontSize: 15,
24
+ suitFontSize: 12,
25
+ },
26
+ small: {
27
+ width: 28,
28
+ height: 40,
29
+ radius: 5,
30
+ rankFontSize: 11,
31
+ suitFontSize: 9,
32
+ },
33
+ };
34
+
35
+ export function getTabletopCardDimensions(size: TabletopCardSize): TabletopCardDimensions {
36
+ return cardDimensions[size];
37
+ }
package/src/colors.ts ADDED
@@ -0,0 +1,67 @@
1
+ export interface TabletopColorScheme {
2
+ readonly cardBack: string;
3
+ readonly cardBackBorder: string;
4
+ readonly cardBorder: string;
5
+ readonly cardSurface: string;
6
+ readonly cardText: string;
7
+ readonly mutedText: string;
8
+ readonly redSuitText: string;
9
+ readonly seatBorder: string;
10
+ readonly seatSelectedBorder: string;
11
+ readonly seatSurface: string;
12
+ readonly tableBorder: string;
13
+ readonly tableFelt: string;
14
+ readonly tableInnerBorder: string;
15
+ readonly tokenSurface: string;
16
+ readonly tokenText: string;
17
+ }
18
+
19
+ export type TabletopColorOverrides = Partial<TabletopColorScheme>;
20
+
21
+ export interface TabletopColorThemeShape {
22
+ semantics: {
23
+ action: {
24
+ primary: {
25
+ base: string;
26
+ softBg: string;
27
+ };
28
+ };
29
+ content: {
30
+ default: string;
31
+ muted: string;
32
+ };
33
+ neutral: {
34
+ border: string;
35
+ divider: string;
36
+ surface: string;
37
+ surfaceHover: string;
38
+ };
39
+ warning: {
40
+ base: string;
41
+ softBg: string;
42
+ };
43
+ };
44
+ }
45
+
46
+ export function createTabletopColorScheme(
47
+ theme: TabletopColorThemeShape,
48
+ overrides: TabletopColorOverrides = {},
49
+ ): TabletopColorScheme {
50
+ return {
51
+ cardBack: overrides.cardBack ?? theme.semantics.warning.base,
52
+ cardBackBorder: overrides.cardBackBorder ?? theme.semantics.neutral.border,
53
+ cardBorder: overrides.cardBorder ?? theme.semantics.neutral.border,
54
+ cardSurface: overrides.cardSurface ?? theme.semantics.neutral.surface,
55
+ cardText: overrides.cardText ?? theme.semantics.content.default,
56
+ mutedText: overrides.mutedText ?? theme.semantics.content.muted,
57
+ redSuitText: overrides.redSuitText ?? theme.semantics.warning.base,
58
+ seatBorder: overrides.seatBorder ?? theme.semantics.neutral.divider,
59
+ seatSelectedBorder: overrides.seatSelectedBorder ?? theme.semantics.action.primary.base,
60
+ seatSurface: overrides.seatSurface ?? theme.semantics.neutral.surface,
61
+ tableBorder: overrides.tableBorder ?? theme.semantics.warning.base,
62
+ tableFelt: overrides.tableFelt ?? theme.semantics.action.primary.softBg,
63
+ tableInnerBorder: overrides.tableInnerBorder ?? theme.semantics.neutral.divider,
64
+ tokenSurface: overrides.tokenSurface ?? theme.semantics.warning.softBg,
65
+ tokenText: overrides.tokenText ?? theme.semantics.content.default,
66
+ };
67
+ }