@ankhorage/zora-tabletop 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/zora-tabletop
2
2
 
3
+ ## 0.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 51c846b: Update packages
8
+
9
+ ## 0.0.3
10
+
11
+ ### Patch Changes
12
+
13
+ - 25a2245: Add Paradox README and usage documentation comments for tabletop UI exports.
14
+
3
15
  ## 0.0.2
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -3,10 +3,92 @@
3
3
 
4
4
  # @ankhorage/zora-tabletop
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v0.0.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v0.0.2](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Reusable tabletop, playing-card, seat, token, and card-game presentation components for React Native and React Native Web.
9
9
 
10
+ ## Usage
11
+
12
+ ### Minimal tabletop app root.
13
+
14
+ Use `TabletopTable` inside a ZORA app shell to render generic seats, visible
15
+ cards, face-down cards, and center-table labels without adding game rules.
16
+
17
+ Source: `examples/basic-tabletop/App.tsx`
18
+
19
+ ```tsx
20
+ import {
21
+ AppBar,
22
+ AppShell,
23
+ Screen,
24
+ ScreenSection,
25
+ ZoraProvider,
26
+ type ZoraTheme,
27
+ } from '@ankhorage/zora';
28
+ import { type TabletopSeatState, TabletopTable } from '@ankhorage/zora-tabletop';
29
+
30
+ const tabletopTheme: ZoraTheme = {
31
+ id: 'basic-tabletop',
32
+ name: 'Basic tabletop',
33
+ appCategory: 'games',
34
+ primaryColor: '#0f766e',
35
+ harmony: 'analogous',
36
+ };
37
+
38
+ const seats: readonly TabletopSeatState[] = [
39
+ {
40
+ id: 'seat-a',
41
+ label: 'Seat A',
42
+ sublabel: 'Ready',
43
+ cards: [
44
+ { rank: 'A', suit: 'spades' },
45
+ { rank: 'K', suit: 'hearts' },
46
+ ],
47
+ selected: true,
48
+ tokenLabel: 'Active',
49
+ },
50
+ {
51
+ id: 'seat-b',
52
+ label: 'Seat B',
53
+ sublabel: 'Hidden cards',
54
+ faceDownCards: 2,
55
+ },
56
+ {
57
+ id: 'seat-c',
58
+ label: 'Seat C',
59
+ sublabel: 'Paused',
60
+ faceDownCards: 2,
61
+ muted: true,
62
+ },
63
+ ];
64
+
65
+ export default function BasicTabletopApp() {
66
+ return (
67
+ <ZoraProvider initialMode="light" theme={tabletopTheme}>
68
+ <AppShell header={<AppBar title="Tabletop" subtitle="Reusable card-game UI" />}>
69
+ <Screen>
70
+ <ScreenSection
71
+ title="Table state"
72
+ description="Map app data into generic seats and cards."
73
+ >
74
+ <TabletopTable
75
+ seats={seats}
76
+ centerCards={[
77
+ { rank: 'Q', suit: 'diamonds' },
78
+ { rank: 'J', suit: 'clubs' },
79
+ { rank: '10', suit: 'spades' },
80
+ ]}
81
+ centerLabel="Round 1"
82
+ centerSublabel="Shared cards"
83
+ />
84
+ </ScreenSection>
85
+ </Screen>
86
+ </AppShell>
87
+ </ZoraProvider>
88
+ );
89
+ }
90
+ ```
91
+
10
92
  ## Generated documentation
11
93
 
12
94
  - [Interactive documentation app](././paradox/index.html)
@@ -20,79 +102,219 @@ Reusable tabletop, playing-card, seat, token, and card-game presentation compone
20
102
  - [PlayingCard sequence](././paradox/diagrams/sequences/playing-card.mmd)
21
103
  - [TabletopTable sequence](././paradox/diagrams/sequences/tabletop-table.mmd)
22
104
 
23
- ## Architecture preview
105
+ ## Public API
106
+
107
+ ### Components
108
+
109
+ <details>
110
+ <summary>CardBack</summary>
111
+
112
+ ```ts
113
+ CardBack({
114
+ size = 'medium',
115
+ muted = false,
116
+ accessibilityLabel,
117
+ colorScheme,
118
+ testID,
119
+ }: CardBackProps) => React.JSX.Element
120
+ ```
121
+
122
+ Face-down playing-card primitive for hidden cards and decks.
123
+
124
+ Use `CardBack` when a card should be represented visually without exposing its
125
+ rank or suit. The component keeps a generic accessible label for hidden cards.
126
+
127
+ #### Hidden cards
128
+
129
+ ```tsx
130
+ <CardBack size="small" />
131
+ ```
132
+
133
+ Related types: `CardBackProps`
134
+
135
+ <details>
136
+ <summary>Props</summary>
137
+
138
+ | Prop | Type | Required | Default | Description |
139
+ | ------------------ | ------------------------------------- | -------- | ---------- | ----------- |
140
+ | accessibilityLabel | `string \| undefined` | no | — | |
141
+ | colorScheme | `TabletopColorOverrides \| undefined` | no | — | |
142
+ | muted | `boolean \| undefined` | no | `false` | |
143
+ | size | `TabletopCardSize \| undefined` | no | `'medium'` | |
144
+ | testID | `string \| undefined` | no | — | |
145
+
146
+ </details>
147
+
148
+ </details>
149
+
150
+ <details>
151
+ <summary>CardHand</summary>
152
+
153
+ ```ts
154
+ CardHand({
155
+ cards = [],
156
+ faceDownCards = 0,
157
+ size = 'medium',
158
+ muted = false,
159
+ colorScheme,
160
+ accessibilityLabel,
161
+ testID,
162
+ }: CardHandProps) => React.JSX.Element
163
+ ```
164
+
165
+ Compact row of visible and face-down playing cards.
166
+
167
+ Use `CardHand` when a seat, pile, or custom layout needs to show multiple cards
168
+ with consistent spacing, sizing, and muted state handling.
169
+
170
+ #### Mixed hand
171
+
172
+ ```tsx
173
+ <CardHand cards={[{ rank: 'Q', suit: 'hearts' }]} faceDownCards={1} />
174
+ ```
175
+
176
+ Related types: `CardHandProps`
177
+
178
+ <details>
179
+ <summary>Props</summary>
180
+
181
+ | Prop | Type | Required | Default | Description |
182
+ | ------------------ | ------------------------------------------ | -------- | ---------- | ----------- |
183
+ | accessibilityLabel | `string \| undefined` | no | — | |
184
+ | cards | `readonly PlayingCardValue[] \| undefined` | no | `[]` | |
185
+ | colorScheme | `TabletopColorOverrides \| undefined` | no | — | |
186
+ | faceDownCards | `number \| undefined` | no | `0` | |
187
+ | muted | `boolean \| undefined` | no | `false` | |
188
+ | size | `TabletopCardSize \| undefined` | no | `'medium'` | |
189
+ | testID | `string \| undefined` | no | — | |
190
+
191
+ </details>
192
+
193
+ </details>
194
+
195
+ <details>
196
+ <summary>PlayingCard</summary>
197
+
198
+ ```ts
199
+ PlayingCard({
200
+ card,
201
+ size = 'medium',
202
+ selected = false,
203
+ muted = false,
204
+ accessibilityLabel,
205
+ colorScheme,
206
+ testID,
207
+ }: PlayingCardProps) => React.JSX.Element
208
+ ```
209
+
210
+ Theme-aware face-up playing card primitive.
211
+
212
+ Use `PlayingCard` for visible card values in hands, shared table cards, piles,
213
+ or custom tabletop layouts. The component renders rank and suit text and exposes
214
+ an accessible card label by default.
215
+
216
+ #### Face-up card
217
+
218
+ ```tsx
219
+ <PlayingCard card={{ rank: 'A', suit: 'spades' }} selected />
220
+ ```
221
+
222
+ Related types: `PlayingCardProps`
24
223
 
25
224
  <details>
26
- <summary>Architecture overview</summary>
27
-
28
- ```mermaid
29
- graph TD
30
- package__ankhorage_zora_tabletop["@ankhorage/zora-tabletop"]
31
- entrypoint_src_index_ts["src/index.ts"]
32
- package__ankhorage_zora_tabletop --> entrypoint_src_index_ts
33
- module_src_cardLabel_ts["src/cardLabel.ts"]
34
- package__ankhorage_zora_tabletop -.-> module_src_cardLabel_ts
35
- module_src_cardLabel_ts --> module_src_types_ts
36
- module_src_cardSizing_ts["src/cardSizing.ts"]
37
- package__ankhorage_zora_tabletop -.-> module_src_cardSizing_ts
38
- module_src_cardSizing_ts --> module_src_types_ts
39
- module_src_colors_ts["src/colors.ts"]
40
- package__ankhorage_zora_tabletop -.-> module_src_colors_ts
41
- module_src_components_card_back_CardBack_tsx["src/components/card-back/CardBack.tsx"]
42
- package__ankhorage_zora_tabletop -.-> module_src_components_card_back_CardBack_tsx
43
- module_src_components_card_back_CardBack_tsx --> module_src_cardLabel_ts
44
- module_src_components_card_back_CardBack_tsx --> module_src_cardSizing_ts
45
- module_src_components_card_back_CardBack_tsx --> module_src_colors_ts
46
- module_src_components_card_back_CardBack_tsx --> module_src_components_card_back_types_ts
47
- module_src_components_card_back_index_ts["src/components/card-back/index.ts"]
48
- package__ankhorage_zora_tabletop -.-> module_src_components_card_back_index_ts
49
- module_src_components_card_back_types_ts["src/components/card-back/types.ts"]
50
- package__ankhorage_zora_tabletop -.-> module_src_components_card_back_types_ts
51
- module_src_components_card_back_types_ts --> module_src_colors_ts
52
- module_src_components_card_back_types_ts --> module_src_types_ts
53
- module_src_components_card_hand_CardHand_tsx["src/components/card-hand/CardHand.tsx"]
54
- package__ankhorage_zora_tabletop -.-> module_src_components_card_hand_CardHand_tsx
55
- module_src_components_card_hand_CardHand_tsx --> module_src_components_card_back_index_ts
56
- module_src_components_card_hand_CardHand_tsx --> module_src_components_card_hand_types_ts
57
- module_src_components_card_hand_CardHand_tsx --> module_src_components_playing_card_index_ts
58
- module_src_components_card_hand_index_ts["src/components/card-hand/index.ts"]
59
- package__ankhorage_zora_tabletop -.-> module_src_components_card_hand_index_ts
60
- module_src_components_card_hand_types_ts["src/components/card-hand/types.ts"]
61
- package__ankhorage_zora_tabletop -.-> module_src_components_card_hand_types_ts
62
- module_src_components_card_hand_types_ts --> module_src_colors_ts
63
- module_src_components_card_hand_types_ts --> module_src_types_ts
64
- module_src_components_playing_card_index_ts["src/components/playing-card/index.ts"]
65
- package__ankhorage_zora_tabletop -.-> module_src_components_playing_card_index_ts
66
- module_src_components_playing_card_PlayingCard_tsx["src/components/playing-card/PlayingCard.tsx"]
67
- package__ankhorage_zora_tabletop -.-> module_src_components_playing_card_PlayingCard_tsx
68
- module_src_components_playing_card_PlayingCard_tsx --> module_src_cardLabel_ts
69
- module_src_components_playing_card_PlayingCard_tsx --> module_src_cardSizing_ts
70
- module_src_components_playing_card_PlayingCard_tsx --> module_src_colors_ts
71
- module_src_components_playing_card_PlayingCard_tsx --> module_src_components_playing_card_types_ts
72
- module_src_components_playing_card_PlayingCard_tsx --> module_src_types_ts
73
- module_src_components_playing_card_types_ts["src/components/playing-card/types.ts"]
74
- package__ankhorage_zora_tabletop -.-> module_src_components_playing_card_types_ts
75
- module_src_components_playing_card_types_ts --> module_src_colors_ts
76
- module_src_components_playing_card_types_ts --> module_src_types_ts
77
- module_src_components_tabletop_table_index_ts["src/components/tabletop-table/index.ts"]
78
- package__ankhorage_zora_tabletop -.-> module_src_components_tabletop_table_index_ts
79
- module_src_components_tabletop_table_TabletopTable_tsx["src/components/tabletop-table/TabletopTable.tsx"]
80
- package__ankhorage_zora_tabletop -.-> module_src_components_tabletop_table_TabletopTable_tsx
81
- module_src_components_tabletop_table_TabletopTable_tsx --> module_src_colors_ts
82
- module_src_components_tabletop_table_TabletopTable_tsx --> module_src_components_card_hand_index_ts
83
- module_src_components_tabletop_table_TabletopTable_tsx --> module_src_components_tabletop_table_types_ts
84
- module_src_components_tabletop_table_TabletopTable_tsx --> module_src_tablePositions_ts
85
- module_src_components_tabletop_table_TabletopTable_tsx --> module_src_types_ts
86
- module_src_components_tabletop_table_types_ts["src/components/tabletop-table/types.ts"]
87
- package__ankhorage_zora_tabletop -.-> module_src_components_tabletop_table_types_ts
88
- module_src_components_tabletop_table_types_ts --> module_src_colors_ts
89
- module_src_components_tabletop_table_types_ts --> module_src_types_ts
90
- module_src_index_ts["src/index.ts"]
91
- module_src_tablePositions_ts["src/tablePositions.ts"]
92
- package__ankhorage_zora_tabletop -.-> module_src_tablePositions_ts
93
- module_src_tablePositions_ts --> module_src_types_ts
94
- module_src_types_ts["src/types.ts"]
95
- package__ankhorage_zora_tabletop -.-> module_src_types_ts
225
+ <summary>Props</summary>
226
+
227
+ | Prop | Type | Required | Default | Description |
228
+ | ------------------ | ------------------------------------- | -------- | ---------- | ----------- |
229
+ | accessibilityLabel | `string \| undefined` | no | — | |
230
+ | card | `PlayingCardValue` | yes | — | |
231
+ | colorScheme | `TabletopColorOverrides \| undefined` | no | — | |
232
+ | muted | `boolean \| undefined` | no | `false` | |
233
+ | selected | `boolean \| undefined` | no | `false` | |
234
+ | size | `TabletopCardSize \| undefined` | no | `'medium'` | |
235
+ | testID | `string \| undefined` | no | — | |
236
+
237
+ </details>
238
+
239
+ </details>
240
+
241
+ <details>
242
+ <summary>TabletopTable</summary>
243
+
244
+ ```ts
245
+ TabletopTable({
246
+ seats,
247
+ centerCards = [],
248
+ centerLabel,
249
+ centerSublabel,
250
+ shape = 'oval',
251
+ seatCount,
252
+ cardSize = 'small',
253
+ disabled = false,
254
+ colorScheme,
255
+ accessibilityLabel,
256
+ testID,
257
+ }: TabletopTableProps) => React.JSX.Element
96
258
  ```
97
259
 
260
+ Responsive tabletop surface for generic card-game and board-game scenes.
261
+
262
+ Use `TabletopTable` to arrange seats around a themed table surface, display
263
+ shared center cards, and show neutral seat labels/tokens without embedding game
264
+ rules into the component.
265
+
266
+ #### Basic table
267
+
268
+ ```tsx
269
+ <TabletopTable seats={seats} centerCards={[{ rank: 'A', suit: 'spades' }]} centerLabel="Round 1" />
270
+ ```
271
+
272
+ Related types: `TabletopTableProps`
273
+
274
+ <details>
275
+ <summary>Props</summary>
276
+
277
+ | Prop | Type | Required | Default | Description |
278
+ | ------------------ | ------------------------------------------ | -------- | --------- | ----------- |
279
+ | accessibilityLabel | `string \| undefined` | no | — | |
280
+ | cardSize | `TabletopCardSize \| undefined` | no | `'small'` | |
281
+ | centerCards | `readonly PlayingCardValue[] \| undefined` | no | `[]` | |
282
+ | centerLabel | `React.ReactNode \| undefined` | no | — | |
283
+ | centerSublabel | `React.ReactNode \| undefined` | no | — | |
284
+ | colorScheme | `TabletopColorOverrides \| undefined` | no | — | |
285
+ | disabled | `boolean \| undefined` | no | `false` | |
286
+ | seatCount | `TabletopSeatCount \| undefined` | no | — | |
287
+ | seats | `readonly TabletopSeatState[]` | yes | — | |
288
+ | shape | `TabletopShape \| undefined` | no | `'oval'` | |
289
+ | testID | `string \| undefined` | no | — | |
290
+
291
+ </details>
292
+
293
+ </details>
294
+
295
+ ### Utilities
296
+
297
+ <details>
298
+ <summary>createTabletopColorScheme</summary>
299
+
300
+ ```ts
301
+ createTabletopColorScheme(theme: TabletopColorThemeShape, overrides?: Partial<TabletopColorScheme>) => TabletopColorScheme
302
+ ```
303
+
304
+ Creates the theme-derived color palette used by tabletop primitives.
305
+
306
+ Use `createTabletopColorScheme` when custom components need to align with the
307
+ same card, table, seat, token, and contrast-aware foreground colors as the
308
+ built-in tabletop components.
309
+
310
+ #### Custom color scheme
311
+
312
+ ```ts
313
+ const colors = createTabletopColorScheme(theme, { tableFelt: '#065f46' });
314
+ ```
315
+
316
+ Module: `src/colors.ts`
317
+ Source: `src/colors.ts:73:1`
318
+ Related symbols: `TabletopColorScheme`
319
+
98
320
  </details>
package/dist/colors.d.ts CHANGED
@@ -44,5 +44,18 @@ export interface TabletopColorThemeShape {
44
44
  };
45
45
  };
46
46
  }
47
+ /***
48
+ * Creates the theme-derived color palette used by tabletop primitives.
49
+ *
50
+ * Use `createTabletopColorScheme` when custom components need to align with the
51
+ * same card, table, seat, token, and contrast-aware foreground colors as the
52
+ * built-in tabletop components.
53
+ *
54
+ * @readme
55
+ * @example Custom color scheme
56
+ * ```ts
57
+ * const colors = createTabletopColorScheme(theme, { tableFelt: '#065f46' });
58
+ * ```
59
+ */
47
60
  export declare function createTabletopColorScheme(theme: TabletopColorThemeShape, overrides?: TabletopColorOverrides): TabletopColorScheme;
48
61
  //# sourceMappingURL=colors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE;QACT,MAAM,EAAE;YACN,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM,CAAC;gBACb,MAAM,EAAE,MAAM,CAAC;aAChB,CAAC;SACH,CAAC;QACF,OAAO,EAAE;YACP,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE,MAAM,CAAC;YAChB,OAAO,EAAE,MAAM,CAAC;YAChB,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,OAAO,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH;AAYD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,uBAAuB,EAC9B,SAAS,GAAE,sBAA2B,GACrC,mBAAmB,CAgDrB"}
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE;QACT,MAAM,EAAE;YACN,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM,CAAC;gBACb,MAAM,EAAE,MAAM,CAAC;aAChB,CAAC;SACH,CAAC;QACF,OAAO,EAAE;YACP,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE,MAAM,CAAC;YAChB,OAAO,EAAE,MAAM,CAAC;YAChB,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,OAAO,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH;AAYD;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,uBAAuB,EAC9B,SAAS,GAAE,sBAA2B,GACrC,mBAAmB,CAgDrB"}
package/dist/colors.js CHANGED
@@ -1,6 +1,19 @@
1
1
  const DARK_TEXT_FALLBACK = '#111827';
2
2
  const LIGHT_TEXT_FALLBACK = '#ffffff';
3
3
  const MINIMUM_READABLE_CONTRAST = 4.5;
4
+ /***
5
+ * Creates the theme-derived color palette used by tabletop primitives.
6
+ *
7
+ * Use `createTabletopColorScheme` when custom components need to align with the
8
+ * same card, table, seat, token, and contrast-aware foreground colors as the
9
+ * built-in tabletop components.
10
+ *
11
+ * @readme
12
+ * @example Custom color scheme
13
+ * ```ts
14
+ * const colors = createTabletopColorScheme(theme, { tableFelt: '#065f46' });
15
+ * ```
16
+ */
4
17
  export function createTabletopColorScheme(theme, overrides = {}) {
5
18
  const cardSurface = overrides.cardSurface ?? theme.semantics.neutral.surface;
6
19
  const seatSurface = overrides.seatSurface ?? theme.semantics.neutral.surface;
@@ -1 +1 @@
1
- {"version":3,"file":"colors.js","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"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","sourcesContent":["export interface TabletopColorScheme {\n readonly cardBack: string;\n readonly cardBackBorder: string;\n readonly cardBorder: string;\n readonly cardSurface: string;\n readonly cardText: string;\n readonly mutedText: string;\n readonly redSuitText: string;\n readonly seatBorder: string;\n readonly seatMutedText: string;\n readonly seatSelectedBorder: string;\n readonly seatSurface: string;\n readonly seatText: string;\n readonly tableBorder: string;\n readonly tableFelt: string;\n readonly tableInnerBorder: string;\n readonly tableMutedText: string;\n readonly tableText: string;\n readonly tokenSurface: string;\n readonly tokenText: string;\n}\n\nexport type TabletopColorOverrides = Partial<TabletopColorScheme>;\n\nexport interface TabletopColorThemeShape {\n semantics: {\n action: {\n primary: {\n base: string;\n softBg: string;\n };\n };\n content: {\n default: string;\n muted: string;\n };\n neutral: {\n border: string;\n divider: string;\n surface: string;\n surfaceHover: string;\n };\n warning: {\n base: string;\n softBg: string;\n };\n };\n}\n\ninterface RgbColor {\n readonly red: number;\n readonly green: number;\n readonly blue: number;\n}\n\nconst DARK_TEXT_FALLBACK = '#111827';\nconst LIGHT_TEXT_FALLBACK = '#ffffff';\nconst MINIMUM_READABLE_CONTRAST = 4.5;\n\nexport function createTabletopColorScheme(\n theme: TabletopColorThemeShape,\n overrides: TabletopColorOverrides = {},\n): TabletopColorScheme {\n const cardSurface = overrides.cardSurface ?? theme.semantics.neutral.surface;\n const seatSurface = overrides.seatSurface ?? theme.semantics.neutral.surface;\n const tableFelt = overrides.tableFelt ?? theme.semantics.action.primary.softBg;\n const tokenSurface = overrides.tokenSurface ?? theme.semantics.warning.softBg;\n\n const cardText =\n overrides.cardText ??\n resolveReadableTextColor(cardSurface, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n const seatText =\n overrides.seatText ??\n resolveReadableTextColor(seatSurface, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n const tableText =\n overrides.tableText ??\n resolveReadableTextColor(tableFelt, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n const tokenText =\n overrides.tokenText ??\n resolveReadableTextColor(tokenSurface, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n\n return {\n cardBack: overrides.cardBack ?? theme.semantics.warning.base,\n cardBackBorder: overrides.cardBackBorder ?? theme.semantics.neutral.border,\n cardBorder: overrides.cardBorder ?? theme.semantics.neutral.border,\n cardSurface,\n cardText,\n mutedText:\n overrides.mutedText ??\n resolveReadableTextColor(cardSurface, theme.semantics.content.muted, cardText),\n redSuitText:\n overrides.redSuitText ??\n resolveReadableTextColor(cardSurface, theme.semantics.warning.base, cardText),\n seatBorder: overrides.seatBorder ?? theme.semantics.neutral.divider,\n seatMutedText:\n overrides.seatMutedText ??\n resolveReadableTextColor(seatSurface, theme.semantics.content.muted, seatText),\n seatSelectedBorder: overrides.seatSelectedBorder ?? theme.semantics.action.primary.base,\n seatSurface,\n seatText,\n tableBorder: overrides.tableBorder ?? theme.semantics.warning.base,\n tableFelt,\n tableInnerBorder: overrides.tableInnerBorder ?? theme.semantics.neutral.divider,\n tableMutedText:\n overrides.tableMutedText ??\n resolveReadableTextColor(tableFelt, theme.semantics.content.muted, tableText),\n tableText,\n tokenSurface,\n tokenText,\n };\n}\n\nfunction resolveReadableTextColor(background: string, preferred: string, fallback: string): string {\n const preferredContrast = getContrastRatio(background, preferred);\n if (preferredContrast !== null && preferredContrast >= MINIMUM_READABLE_CONTRAST) {\n return preferred;\n }\n\n const candidates = uniqueColors([preferred, fallback, LIGHT_TEXT_FALLBACK, DARK_TEXT_FALLBACK]);\n const [readableCandidate] = candidates\n .map((candidate) => ({ candidate, contrast: getContrastRatio(background, candidate) }))\n .filter(\n (entry): entry is { readonly candidate: string; readonly contrast: number } =>\n entry.contrast !== null,\n )\n .sort((left, right) => right.contrast - left.contrast);\n\n return readableCandidate?.candidate ?? preferred;\n}\n\nfunction uniqueColors(colors: readonly string[]): string[] {\n return [...new Set(colors)];\n}\n\nfunction getContrastRatio(background: string, foreground: string): number | null {\n const backgroundColor = parseHexColor(background);\n const foregroundColor = parseHexColor(foreground);\n\n if (backgroundColor === null || foregroundColor === null) return null;\n\n const backgroundLuminance = getRelativeLuminance(backgroundColor);\n const foregroundLuminance = getRelativeLuminance(foregroundColor);\n const lighter = Math.max(backgroundLuminance, foregroundLuminance);\n const darker = Math.min(backgroundLuminance, foregroundLuminance);\n\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nfunction parseHexColor(color: string): RgbColor | null {\n const value = color.trim();\n const hex = value.startsWith('#') ? value.slice(1) : '';\n if (!isSupportedHexLength(hex) || !isHexColorValue(hex)) return null;\n\n if (hex.length === 3) {\n const red = hex.slice(0, 1);\n const green = hex.slice(1, 2);\n const blue = hex.slice(2, 3);\n\n return {\n red: parseInt(red + red, 16),\n green: parseInt(green + green, 16),\n blue: parseInt(blue + blue, 16),\n };\n }\n\n return {\n red: parseInt(hex.slice(0, 2), 16),\n green: parseInt(hex.slice(2, 4), 16),\n blue: parseInt(hex.slice(4, 6), 16),\n };\n}\n\nfunction isSupportedHexLength(hex: string): boolean {\n return hex.length === 3 || hex.length === 6 || hex.length === 8;\n}\n\nfunction isHexColorValue(hex: string): boolean {\n return [...hex].every((character) => isHexCharacter(character));\n}\n\nfunction isHexCharacter(character: string): boolean {\n const code = character.charCodeAt(0);\n const isDigit = code >= 48 && code <= 57;\n const isUpperHex = code >= 65 && code <= 70;\n const isLowerHex = code >= 97 && code <= 102;\n\n return isDigit || isUpperHex || isLowerHex;\n}\n\nfunction getRelativeLuminance(color: RgbColor): number {\n const red = normalizeColorChannel(color.red);\n const green = normalizeColorChannel(color.green);\n const blue = normalizeColorChannel(color.blue);\n\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n}\n\nfunction normalizeColorChannel(value: number): number {\n const normalized = value / 255;\n if (normalized <= 0.03928) return normalized / 12.92;\n return ((normalized + 0.055) / 1.055) ** 2.4;\n}\n"]}
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"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","sourcesContent":["export interface TabletopColorScheme {\n readonly cardBack: string;\n readonly cardBackBorder: string;\n readonly cardBorder: string;\n readonly cardSurface: string;\n readonly cardText: string;\n readonly mutedText: string;\n readonly redSuitText: string;\n readonly seatBorder: string;\n readonly seatMutedText: string;\n readonly seatSelectedBorder: string;\n readonly seatSurface: string;\n readonly seatText: string;\n readonly tableBorder: string;\n readonly tableFelt: string;\n readonly tableInnerBorder: string;\n readonly tableMutedText: string;\n readonly tableText: string;\n readonly tokenSurface: string;\n readonly tokenText: string;\n}\n\nexport type TabletopColorOverrides = Partial<TabletopColorScheme>;\n\nexport interface TabletopColorThemeShape {\n semantics: {\n action: {\n primary: {\n base: string;\n softBg: string;\n };\n };\n content: {\n default: string;\n muted: string;\n };\n neutral: {\n border: string;\n divider: string;\n surface: string;\n surfaceHover: string;\n };\n warning: {\n base: string;\n softBg: string;\n };\n };\n}\n\ninterface RgbColor {\n readonly red: number;\n readonly green: number;\n readonly blue: number;\n}\n\nconst DARK_TEXT_FALLBACK = '#111827';\nconst LIGHT_TEXT_FALLBACK = '#ffffff';\nconst MINIMUM_READABLE_CONTRAST = 4.5;\n\n/***\n * Creates the theme-derived color palette used by tabletop primitives.\n *\n * Use `createTabletopColorScheme` when custom components need to align with the\n * same card, table, seat, token, and contrast-aware foreground colors as the\n * built-in tabletop components.\n *\n * @readme\n * @example Custom color scheme\n * ```ts\n * const colors = createTabletopColorScheme(theme, { tableFelt: '#065f46' });\n * ```\n */\nexport function createTabletopColorScheme(\n theme: TabletopColorThemeShape,\n overrides: TabletopColorOverrides = {},\n): TabletopColorScheme {\n const cardSurface = overrides.cardSurface ?? theme.semantics.neutral.surface;\n const seatSurface = overrides.seatSurface ?? theme.semantics.neutral.surface;\n const tableFelt = overrides.tableFelt ?? theme.semantics.action.primary.softBg;\n const tokenSurface = overrides.tokenSurface ?? theme.semantics.warning.softBg;\n\n const cardText =\n overrides.cardText ??\n resolveReadableTextColor(cardSurface, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n const seatText =\n overrides.seatText ??\n resolveReadableTextColor(seatSurface, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n const tableText =\n overrides.tableText ??\n resolveReadableTextColor(tableFelt, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n const tokenText =\n overrides.tokenText ??\n resolveReadableTextColor(tokenSurface, theme.semantics.content.default, LIGHT_TEXT_FALLBACK);\n\n return {\n cardBack: overrides.cardBack ?? theme.semantics.warning.base,\n cardBackBorder: overrides.cardBackBorder ?? theme.semantics.neutral.border,\n cardBorder: overrides.cardBorder ?? theme.semantics.neutral.border,\n cardSurface,\n cardText,\n mutedText:\n overrides.mutedText ??\n resolveReadableTextColor(cardSurface, theme.semantics.content.muted, cardText),\n redSuitText:\n overrides.redSuitText ??\n resolveReadableTextColor(cardSurface, theme.semantics.warning.base, cardText),\n seatBorder: overrides.seatBorder ?? theme.semantics.neutral.divider,\n seatMutedText:\n overrides.seatMutedText ??\n resolveReadableTextColor(seatSurface, theme.semantics.content.muted, seatText),\n seatSelectedBorder: overrides.seatSelectedBorder ?? theme.semantics.action.primary.base,\n seatSurface,\n seatText,\n tableBorder: overrides.tableBorder ?? theme.semantics.warning.base,\n tableFelt,\n tableInnerBorder: overrides.tableInnerBorder ?? theme.semantics.neutral.divider,\n tableMutedText:\n overrides.tableMutedText ??\n resolveReadableTextColor(tableFelt, theme.semantics.content.muted, tableText),\n tableText,\n tokenSurface,\n tokenText,\n };\n}\n\nfunction resolveReadableTextColor(background: string, preferred: string, fallback: string): string {\n const preferredContrast = getContrastRatio(background, preferred);\n if (preferredContrast !== null && preferredContrast >= MINIMUM_READABLE_CONTRAST) {\n return preferred;\n }\n\n const candidates = uniqueColors([preferred, fallback, LIGHT_TEXT_FALLBACK, DARK_TEXT_FALLBACK]);\n const [readableCandidate] = candidates\n .map((candidate) => ({ candidate, contrast: getContrastRatio(background, candidate) }))\n .filter(\n (entry): entry is { readonly candidate: string; readonly contrast: number } =>\n entry.contrast !== null,\n )\n .sort((left, right) => right.contrast - left.contrast);\n\n return readableCandidate?.candidate ?? preferred;\n}\n\nfunction uniqueColors(colors: readonly string[]): string[] {\n return [...new Set(colors)];\n}\n\nfunction getContrastRatio(background: string, foreground: string): number | null {\n const backgroundColor = parseHexColor(background);\n const foregroundColor = parseHexColor(foreground);\n\n if (backgroundColor === null || foregroundColor === null) return null;\n\n const backgroundLuminance = getRelativeLuminance(backgroundColor);\n const foregroundLuminance = getRelativeLuminance(foregroundColor);\n const lighter = Math.max(backgroundLuminance, foregroundLuminance);\n const darker = Math.min(backgroundLuminance, foregroundLuminance);\n\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nfunction parseHexColor(color: string): RgbColor | null {\n const value = color.trim();\n const hex = value.startsWith('#') ? value.slice(1) : '';\n if (!isSupportedHexLength(hex) || !isHexColorValue(hex)) return null;\n\n if (hex.length === 3) {\n const red = hex.slice(0, 1);\n const green = hex.slice(1, 2);\n const blue = hex.slice(2, 3);\n\n return {\n red: parseInt(red + red, 16),\n green: parseInt(green + green, 16),\n blue: parseInt(blue + blue, 16),\n };\n }\n\n return {\n red: parseInt(hex.slice(0, 2), 16),\n green: parseInt(hex.slice(2, 4), 16),\n blue: parseInt(hex.slice(4, 6), 16),\n };\n}\n\nfunction isSupportedHexLength(hex: string): boolean {\n return hex.length === 3 || hex.length === 6 || hex.length === 8;\n}\n\nfunction isHexColorValue(hex: string): boolean {\n return [...hex].every((character) => isHexCharacter(character));\n}\n\nfunction isHexCharacter(character: string): boolean {\n const code = character.charCodeAt(0);\n const isDigit = code >= 48 && code <= 57;\n const isUpperHex = code >= 65 && code <= 70;\n const isLowerHex = code >= 97 && code <= 102;\n\n return isDigit || isUpperHex || isLowerHex;\n}\n\nfunction getRelativeLuminance(color: RgbColor): number {\n const red = normalizeColorChannel(color.red);\n const green = normalizeColorChannel(color.green);\n const blue = normalizeColorChannel(color.blue);\n\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n}\n\nfunction normalizeColorChannel(value: number): number {\n const normalized = value / 255;\n if (normalized <= 0.03928) return normalized / 12.92;\n return ((normalized + 0.055) / 1.055) ** 2.4;\n}\n"]}
@@ -1,4 +1,16 @@
1
1
  import React from 'react';
2
2
  import type { CardBackProps } from './types';
3
+ /***
4
+ * Face-down playing-card primitive for hidden cards and decks.
5
+ *
6
+ * Use `CardBack` when a card should be represented visually without exposing its
7
+ * rank or suit. The component keeps a generic accessible label for hidden cards.
8
+ *
9
+ * @readme
10
+ * @example Hidden cards
11
+ * ```tsx
12
+ * <CardBack size="small" />
13
+ * ```
14
+ */
3
15
  export declare function CardBack({ size, muted, accessibilityLabel, colorScheme, testID, }: CardBackProps): React.JSX.Element;
4
16
  //# sourceMappingURL=CardBack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CardBack.d.ts","sourceRoot":"","sources":["../../../src/components/card-back/CardBack.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,QAAQ,CAAC,EACvB,IAAe,EACf,KAAa,EACb,kBAAkB,EAClB,WAAW,EACX,MAAM,GACP,EAAE,aAAa,qBAoCf"}
1
+ {"version":3,"file":"CardBack.d.ts","sourceRoot":"","sources":["../../../src/components/card-back/CardBack.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,EACvB,IAAe,EACf,KAAa,EACb,kBAAkB,EAClB,WAAW,EACX,MAAM,GACP,EAAE,aAAa,qBAoCf"}
@@ -4,6 +4,18 @@ import { StyleSheet, View } from 'react-native';
4
4
  import { createHiddenCardLabel } from '../../cardLabel';
5
5
  import { getTabletopCardDimensions } from '../../cardSizing';
6
6
  import { createTabletopColorScheme } from '../../colors';
7
+ /***
8
+ * Face-down playing-card primitive for hidden cards and decks.
9
+ *
10
+ * Use `CardBack` when a card should be represented visually without exposing its
11
+ * rank or suit. The component keeps a generic accessible label for hidden cards.
12
+ *
13
+ * @readme
14
+ * @example Hidden cards
15
+ * ```tsx
16
+ * <CardBack size="small" />
17
+ * ```
18
+ */
7
19
  export function CardBack({ size = 'medium', muted = false, accessibilityLabel, colorScheme, testID, }) {
8
20
  const { theme } = useZoraTheme();
9
21
  const colors = React.useMemo(() => createTabletopColorScheme(theme, colorScheme), [colorScheme, theme]);
@@ -1 +1 @@
1
- {"version":3,"file":"CardBack.js","sourceRoot":"","sources":["../../../src/components/card-back/CardBack.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,UAAU,QAAQ,CAAC,EACvB,IAAI,GAAG,QAAQ,EACf,KAAK,GAAG,KAAK,EACb,kBAAkB,EAClB,WAAW,EACX,MAAM,GACQ;IACd,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC,yBAAyB,CAAC,KAAK,EAAE,WAAW,CAAC,EACnD,CAAC,WAAW,EAAE,KAAK,CAAC,CACrB,CAAC;IACF,MAAM,UAAU,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAEnD,OAAO,CACL,CAAC,IAAI,CACH,kBAAkB,CAAC,CAAC,kBAAkB,IAAI,qBAAqB,EAAE,CAAC,CAClE,iBAAiB,CAAC,OAAO,CACzB,KAAK,CAAC,CAAC;YACL,MAAM,CAAC,IAAI;YACX;gBACE,eAAe,EAAE,MAAM,CAAC,QAAQ;gBAChC,WAAW,EAAE,MAAM,CAAC,cAAc;gBAClC,YAAY,EAAE,UAAU,CAAC,MAAM;gBAC/B,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,KAAK,EAAE,UAAU,CAAC,KAAK;aACxB;SACF,CAAC,CACF,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,IAAI,CACH,KAAK,CAAC,CAAC;YACL,MAAM,CAAC,KAAK;YACZ;gBACE,WAAW,EAAE,MAAM,CAAC,cAAc;gBAClC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;aACjD;SACF,CAAC,EAEN;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE;QACJ,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,CAAC;QACd,cAAc,EAAE,QAAQ;KACzB;IACD,KAAK,EAAE;QACL,WAAW,EAAE,CAAC;QACd,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,KAAK;KACb;CACF,CAAC,CAAC","sourcesContent":["import { useZoraTheme } from '@ankhorage/zora';\nimport React from 'react';\nimport { StyleSheet, View } from 'react-native';\n\nimport { createHiddenCardLabel } from '../../cardLabel';\nimport { getTabletopCardDimensions } from '../../cardSizing';\nimport { createTabletopColorScheme } from '../../colors';\nimport type { CardBackProps } from './types';\n\nexport function CardBack({\n size = 'medium',\n muted = false,\n accessibilityLabel,\n colorScheme,\n testID,\n}: CardBackProps) {\n const { theme } = useZoraTheme();\n const colors = React.useMemo(\n () => createTabletopColorScheme(theme, colorScheme),\n [colorScheme, theme],\n );\n const dimensions = getTabletopCardDimensions(size);\n\n return (\n <View\n accessibilityLabel={accessibilityLabel ?? createHiddenCardLabel()}\n accessibilityRole=\"image\"\n style={[\n styles.card,\n {\n backgroundColor: colors.cardBack,\n borderColor: colors.cardBackBorder,\n borderRadius: dimensions.radius,\n height: dimensions.height,\n opacity: muted ? 0.48 : 1,\n width: dimensions.width,\n },\n ]}\n testID={testID}\n >\n <View\n style={[\n styles.inner,\n {\n borderColor: colors.cardBackBorder,\n borderRadius: Math.max(2, dimensions.radius - 3),\n },\n ]}\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n card: {\n alignItems: 'center',\n borderWidth: 1,\n justifyContent: 'center',\n },\n inner: {\n borderWidth: 1,\n height: '68%',\n opacity: 0.48,\n width: '68%',\n },\n});\n"]}
1
+ {"version":3,"file":"CardBack.js","sourceRoot":"","sources":["../../../src/components/card-back/CardBack.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAGzD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,IAAI,GAAG,QAAQ,EACf,KAAK,GAAG,KAAK,EACb,kBAAkB,EAClB,WAAW,EACX,MAAM,GACQ;IACd,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC,yBAAyB,CAAC,KAAK,EAAE,WAAW,CAAC,EACnD,CAAC,WAAW,EAAE,KAAK,CAAC,CACrB,CAAC;IACF,MAAM,UAAU,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAEnD,OAAO,CACL,CAAC,IAAI,CACH,kBAAkB,CAAC,CAAC,kBAAkB,IAAI,qBAAqB,EAAE,CAAC,CAClE,iBAAiB,CAAC,OAAO,CACzB,KAAK,CAAC,CAAC;YACL,MAAM,CAAC,IAAI;YACX;gBACE,eAAe,EAAE,MAAM,CAAC,QAAQ;gBAChC,WAAW,EAAE,MAAM,CAAC,cAAc;gBAClC,YAAY,EAAE,UAAU,CAAC,MAAM;gBAC/B,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,KAAK,EAAE,UAAU,CAAC,KAAK;aACxB;SACF,CAAC,CACF,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,IAAI,CACH,KAAK,CAAC,CAAC;YACL,MAAM,CAAC,KAAK;YACZ;gBACE,WAAW,EAAE,MAAM,CAAC,cAAc;gBAClC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;aACjD;SACF,CAAC,EAEN;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE;QACJ,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,CAAC;QACd,cAAc,EAAE,QAAQ;KACzB;IACD,KAAK,EAAE;QACL,WAAW,EAAE,CAAC;QACd,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,KAAK;KACb;CACF,CAAC,CAAC","sourcesContent":["import { useZoraTheme } from '@ankhorage/zora';\nimport React from 'react';\nimport { StyleSheet, View } from 'react-native';\n\nimport { createHiddenCardLabel } from '../../cardLabel';\nimport { getTabletopCardDimensions } from '../../cardSizing';\nimport { createTabletopColorScheme } from '../../colors';\nimport type { CardBackProps } from './types';\n\n/***\n * Face-down playing-card primitive for hidden cards and decks.\n *\n * Use `CardBack` when a card should be represented visually without exposing its\n * rank or suit. The component keeps a generic accessible label for hidden cards.\n *\n * @readme\n * @example Hidden cards\n * ```tsx\n * <CardBack size=\"small\" />\n * ```\n */\nexport function CardBack({\n size = 'medium',\n muted = false,\n accessibilityLabel,\n colorScheme,\n testID,\n}: CardBackProps) {\n const { theme } = useZoraTheme();\n const colors = React.useMemo(\n () => createTabletopColorScheme(theme, colorScheme),\n [colorScheme, theme],\n );\n const dimensions = getTabletopCardDimensions(size);\n\n return (\n <View\n accessibilityLabel={accessibilityLabel ?? createHiddenCardLabel()}\n accessibilityRole=\"image\"\n style={[\n styles.card,\n {\n backgroundColor: colors.cardBack,\n borderColor: colors.cardBackBorder,\n borderRadius: dimensions.radius,\n height: dimensions.height,\n opacity: muted ? 0.48 : 1,\n width: dimensions.width,\n },\n ]}\n testID={testID}\n >\n <View\n style={[\n styles.inner,\n {\n borderColor: colors.cardBackBorder,\n borderRadius: Math.max(2, dimensions.radius - 3),\n },\n ]}\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n card: {\n alignItems: 'center',\n borderWidth: 1,\n justifyContent: 'center',\n },\n inner: {\n borderWidth: 1,\n height: '68%',\n opacity: 0.48,\n width: '68%',\n },\n});\n"]}
@@ -1,4 +1,16 @@
1
1
  import React from 'react';
2
2
  import type { CardHandProps } from './types';
3
+ /***
4
+ * Compact row of visible and face-down playing cards.
5
+ *
6
+ * Use `CardHand` when a seat, pile, or custom layout needs to show multiple cards
7
+ * with consistent spacing, sizing, and muted state handling.
8
+ *
9
+ * @readme
10
+ * @example Mixed hand
11
+ * ```tsx
12
+ * <CardHand cards={[{ rank: 'Q', suit: 'hearts' }]} faceDownCards={1} />
13
+ * ```
14
+ */
3
15
  export declare function CardHand({ cards, faceDownCards, size, muted, colorScheme, accessibilityLabel, testID, }: CardHandProps): React.JSX.Element;
4
16
  //# sourceMappingURL=CardHand.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CardHand.d.ts","sourceRoot":"","sources":["../../../src/components/card-hand/CardHand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAM7C,wBAAgB,QAAQ,CAAC,EACvB,KAAU,EACV,aAAiB,EACjB,IAAe,EACf,KAAa,EACb,WAAW,EACX,kBAAkB,EAClB,MAAM,GACP,EAAE,aAAa,qBA0Bf"}
1
+ {"version":3,"file":"CardHand.d.ts","sourceRoot":"","sources":["../../../src/components/card-hand/CardHand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAM7C;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAU,EACV,aAAiB,EACjB,IAAe,EACf,KAAa,EACb,WAAW,EACX,kBAAkB,EAClB,MAAM,GACP,EAAE,aAAa,qBA0Bf"}
@@ -5,6 +5,18 @@ import { PlayingCard } from '../playing-card';
5
5
  function createFaceDownCards(count) {
6
6
  return Array.from({ length: Math.max(0, count) }, (_, index) => index);
7
7
  }
8
+ /***
9
+ * Compact row of visible and face-down playing cards.
10
+ *
11
+ * Use `CardHand` when a seat, pile, or custom layout needs to show multiple cards
12
+ * with consistent spacing, sizing, and muted state handling.
13
+ *
14
+ * @readme
15
+ * @example Mixed hand
16
+ * ```tsx
17
+ * <CardHand cards={[{ rank: 'Q', suit: 'hearts' }]} faceDownCards={1} />
18
+ * ```
19
+ */
8
20
  export function CardHand({ cards = [], faceDownCards = 0, size = 'medium', muted = false, colorScheme, accessibilityLabel, testID, }) {
9
21
  const hiddenCards = createFaceDownCards(faceDownCards);
10
22
  return (<View accessibilityLabel={accessibilityLabel} style={styles.hand} testID={testID}>
@@ -1 +1 @@
1
- {"version":3,"file":"CardHand.js","sourceRoot":"","sources":["../../../src/components/card-hand/CardHand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,GAAG,EAAE,EACV,aAAa,GAAG,CAAC,EACjB,IAAI,GAAG,QAAQ,EACf,KAAK,GAAG,KAAK,EACb,WAAW,EACX,kBAAkB,EAClB,MAAM,GACQ;IACd,MAAM,WAAW,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAEvD,OAAO,CACL,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAC/E;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,CAAC,WAAW,CACV,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAC1C,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EACvD,CACH,CAAC,CACF;MAAA,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC1B,CAAC,QAAQ,CACP,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,GAAG,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CACvB,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EACzD,CACH,CAAC,CACJ;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE;QACJ,UAAU,EAAE,QAAQ;QACpB,aAAa,EAAE,KAAK;QACpB,GAAG,EAAE,CAAC;QACN,cAAc,EAAE,QAAQ;KACzB;CACF,CAAC,CAAC","sourcesContent":["import React from 'react';\nimport { StyleSheet, View } from 'react-native';\n\nimport { CardBack } from '../card-back';\nimport { PlayingCard } from '../playing-card';\nimport type { CardHandProps } from './types';\n\nfunction createFaceDownCards(count: number): readonly number[] {\n return Array.from({ length: Math.max(0, count) }, (_, index) => index);\n}\n\nexport function CardHand({\n cards = [],\n faceDownCards = 0,\n size = 'medium',\n muted = false,\n colorScheme,\n accessibilityLabel,\n testID,\n}: CardHandProps) {\n const hiddenCards = createFaceDownCards(faceDownCards);\n\n return (\n <View accessibilityLabel={accessibilityLabel} style={styles.hand} testID={testID}>\n {cards.map((card, index) => (\n <PlayingCard\n card={card}\n colorScheme={colorScheme}\n key={`${card.rank}-${card.suit}-${index}`}\n muted={muted}\n size={size}\n testID={testID ? `${testID}-card-${index}` : undefined}\n />\n ))}\n {hiddenCards.map((index) => (\n <CardBack\n colorScheme={colorScheme}\n key={`hidden-${index}`}\n muted={muted}\n size={size}\n testID={testID ? `${testID}-hidden-${index}` : undefined}\n />\n ))}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n hand: {\n alignItems: 'center',\n flexDirection: 'row',\n gap: 4,\n justifyContent: 'center',\n },\n});\n"]}
1
+ {"version":3,"file":"CardHand.js","sourceRoot":"","sources":["../../../src/components/card-hand/CardHand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,GAAG,EAAE,EACV,aAAa,GAAG,CAAC,EACjB,IAAI,GAAG,QAAQ,EACf,KAAK,GAAG,KAAK,EACb,WAAW,EACX,kBAAkB,EAClB,MAAM,GACQ;IACd,MAAM,WAAW,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAEvD,OAAO,CACL,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAC/E;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,CAAC,WAAW,CACV,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAC1C,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EACvD,CACH,CAAC,CACF;MAAA,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC1B,CAAC,QAAQ,CACP,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,GAAG,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CACvB,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EACzD,CACH,CAAC,CACJ;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE;QACJ,UAAU,EAAE,QAAQ;QACpB,aAAa,EAAE,KAAK;QACpB,GAAG,EAAE,CAAC;QACN,cAAc,EAAE,QAAQ;KACzB;CACF,CAAC,CAAC","sourcesContent":["import React from 'react';\nimport { StyleSheet, View } from 'react-native';\n\nimport { CardBack } from '../card-back';\nimport { PlayingCard } from '../playing-card';\nimport type { CardHandProps } from './types';\n\nfunction createFaceDownCards(count: number): readonly number[] {\n return Array.from({ length: Math.max(0, count) }, (_, index) => index);\n}\n\n/***\n * Compact row of visible and face-down playing cards.\n *\n * Use `CardHand` when a seat, pile, or custom layout needs to show multiple cards\n * with consistent spacing, sizing, and muted state handling.\n *\n * @readme\n * @example Mixed hand\n * ```tsx\n * <CardHand cards={[{ rank: 'Q', suit: 'hearts' }]} faceDownCards={1} />\n * ```\n */\nexport function CardHand({\n cards = [],\n faceDownCards = 0,\n size = 'medium',\n muted = false,\n colorScheme,\n accessibilityLabel,\n testID,\n}: CardHandProps) {\n const hiddenCards = createFaceDownCards(faceDownCards);\n\n return (\n <View accessibilityLabel={accessibilityLabel} style={styles.hand} testID={testID}>\n {cards.map((card, index) => (\n <PlayingCard\n card={card}\n colorScheme={colorScheme}\n key={`${card.rank}-${card.suit}-${index}`}\n muted={muted}\n size={size}\n testID={testID ? `${testID}-card-${index}` : undefined}\n />\n ))}\n {hiddenCards.map((index) => (\n <CardBack\n colorScheme={colorScheme}\n key={`hidden-${index}`}\n muted={muted}\n size={size}\n testID={testID ? `${testID}-hidden-${index}` : undefined}\n />\n ))}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n hand: {\n alignItems: 'center',\n flexDirection: 'row',\n gap: 4,\n justifyContent: 'center',\n },\n});\n"]}
@@ -1,4 +1,17 @@
1
1
  import React from 'react';
2
2
  import type { PlayingCardProps } from './types';
3
+ /***
4
+ * Theme-aware face-up playing card primitive.
5
+ *
6
+ * Use `PlayingCard` for visible card values in hands, shared table cards, piles,
7
+ * or custom tabletop layouts. The component renders rank and suit text and exposes
8
+ * an accessible card label by default.
9
+ *
10
+ * @readme
11
+ * @example Face-up card
12
+ * ```tsx
13
+ * <PlayingCard card={{ rank: 'A', suit: 'spades' }} selected />
14
+ * ```
15
+ */
3
16
  export declare function PlayingCard({ card, size, selected, muted, accessibilityLabel, colorScheme, testID, }: PlayingCardProps): React.JSX.Element;
4
17
  //# sourceMappingURL=PlayingCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlayingCard.d.ts","sourceRoot":"","sources":["../../../src/components/playing-card/PlayingCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAahD,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,IAAe,EACf,QAAgB,EAChB,KAAa,EACb,kBAAkB,EAClB,WAAW,EACX,MAAM,GACP,EAAE,gBAAgB,qBAsDlB"}
1
+ {"version":3,"file":"PlayingCard.d.ts","sourceRoot":"","sources":["../../../src/components/playing-card/PlayingCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAahD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,IAAe,EACf,QAAgB,EAChB,KAAa,EACb,kBAAkB,EAClB,WAAW,EACX,MAAM,GACP,EAAE,gBAAgB,qBAsDlB"}
@@ -13,6 +13,19 @@ const suitMarks = {
13
13
  function isRedSuit(suit) {
14
14
  return suit === 'diamonds' || suit === 'hearts';
15
15
  }
16
+ /***
17
+ * Theme-aware face-up playing card primitive.
18
+ *
19
+ * Use `PlayingCard` for visible card values in hands, shared table cards, piles,
20
+ * or custom tabletop layouts. The component renders rank and suit text and exposes
21
+ * an accessible card label by default.
22
+ *
23
+ * @readme
24
+ * @example Face-up card
25
+ * ```tsx
26
+ * <PlayingCard card={{ rank: 'A', suit: 'spades' }} selected />
27
+ * ```
28
+ */
16
29
  export function PlayingCard({ card, size = 'medium', selected = false, muted = false, accessibilityLabel, colorScheme, testID, }) {
17
30
  const { theme } = useZoraTheme();
18
31
  const colors = React.useMemo(() => createTabletopColorScheme(theme, colorScheme), [colorScheme, theme]);
@@ -1 +1 @@
1
- {"version":3,"file":"PlayingCard.js","sourceRoot":"","sources":["../../../src/components/playing-card/PlayingCard.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 { getPlayingCardLabel } from '../../cardLabel';\nimport { getTabletopCardDimensions } from '../../cardSizing';\nimport { createTabletopColorScheme } from '../../colors';\nimport type { PlayingCardSuit } from '../../types';\nimport type { PlayingCardProps } from './types';\n\nconst suitMarks: Readonly<Record<PlayingCardSuit, string>> = {\n clubs: 'C',\n diamonds: 'D',\n hearts: 'H',\n spades: 'S',\n};\n\nfunction isRedSuit(suit: PlayingCardSuit): boolean {\n return suit === 'diamonds' || suit === 'hearts';\n}\n\nexport function PlayingCard({\n card,\n size = 'medium',\n selected = false,\n muted = false,\n accessibilityLabel,\n colorScheme,\n testID,\n}: PlayingCardProps) {\n const { theme } = useZoraTheme();\n const colors = React.useMemo(\n () => createTabletopColorScheme(theme, colorScheme),\n [colorScheme, theme],\n );\n const dimensions = getTabletopCardDimensions(size);\n const suitColor = isRedSuit(card.suit) ? colors.redSuitText : colors.cardText;\n\n return (\n <View\n accessibilityLabel={accessibilityLabel ?? getPlayingCardLabel(card)}\n accessibilityRole=\"image\"\n style={[\n styles.card,\n {\n backgroundColor: colors.cardSurface,\n borderColor: selected ? colors.seatSelectedBorder : colors.cardBorder,\n borderRadius: dimensions.radius,\n height: dimensions.height,\n opacity: muted ? 0.48 : 1,\n width: dimensions.width,\n },\n ]}\n testID={testID}\n >\n <Text\n selectable={false}\n style={[\n styles.rank,\n {\n color: suitColor,\n fontSize: dimensions.rankFontSize,\n lineHeight: dimensions.rankFontSize + 4,\n },\n ]}\n >\n {card.rank}\n </Text>\n <Text\n selectable={false}\n style={[\n styles.suit,\n {\n color: suitColor,\n fontSize: dimensions.suitFontSize,\n lineHeight: dimensions.suitFontSize + 3,\n },\n ]}\n >\n {suitMarks[card.suit]}\n </Text>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n card: {\n alignItems: 'center',\n borderWidth: 1,\n justifyContent: 'center',\n },\n rank: {\n fontWeight: '800',\n },\n suit: {\n fontWeight: '700',\n marginTop: -2,\n },\n});\n"]}
1
+ {"version":3,"file":"PlayingCard.js","sourceRoot":"","sources":["../../../src/components/playing-card/PlayingCard.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 { getPlayingCardLabel } from '../../cardLabel';\nimport { getTabletopCardDimensions } from '../../cardSizing';\nimport { createTabletopColorScheme } from '../../colors';\nimport type { PlayingCardSuit } from '../../types';\nimport type { PlayingCardProps } from './types';\n\nconst suitMarks: Readonly<Record<PlayingCardSuit, string>> = {\n clubs: 'C',\n diamonds: 'D',\n hearts: 'H',\n spades: 'S',\n};\n\nfunction isRedSuit(suit: PlayingCardSuit): boolean {\n return suit === 'diamonds' || suit === 'hearts';\n}\n\n/***\n * Theme-aware face-up playing card primitive.\n *\n * Use `PlayingCard` for visible card values in hands, shared table cards, piles,\n * or custom tabletop layouts. The component renders rank and suit text and exposes\n * an accessible card label by default.\n *\n * @readme\n * @example Face-up card\n * ```tsx\n * <PlayingCard card={{ rank: 'A', suit: 'spades' }} selected />\n * ```\n */\nexport function PlayingCard({\n card,\n size = 'medium',\n selected = false,\n muted = false,\n accessibilityLabel,\n colorScheme,\n testID,\n}: PlayingCardProps) {\n const { theme } = useZoraTheme();\n const colors = React.useMemo(\n () => createTabletopColorScheme(theme, colorScheme),\n [colorScheme, theme],\n );\n const dimensions = getTabletopCardDimensions(size);\n const suitColor = isRedSuit(card.suit) ? colors.redSuitText : colors.cardText;\n\n return (\n <View\n accessibilityLabel={accessibilityLabel ?? getPlayingCardLabel(card)}\n accessibilityRole=\"image\"\n style={[\n styles.card,\n {\n backgroundColor: colors.cardSurface,\n borderColor: selected ? colors.seatSelectedBorder : colors.cardBorder,\n borderRadius: dimensions.radius,\n height: dimensions.height,\n opacity: muted ? 0.48 : 1,\n width: dimensions.width,\n },\n ]}\n testID={testID}\n >\n <Text\n selectable={false}\n style={[\n styles.rank,\n {\n color: suitColor,\n fontSize: dimensions.rankFontSize,\n lineHeight: dimensions.rankFontSize + 4,\n },\n ]}\n >\n {card.rank}\n </Text>\n <Text\n selectable={false}\n style={[\n styles.suit,\n {\n color: suitColor,\n fontSize: dimensions.suitFontSize,\n lineHeight: dimensions.suitFontSize + 3,\n },\n ]}\n >\n {suitMarks[card.suit]}\n </Text>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n card: {\n alignItems: 'center',\n borderWidth: 1,\n justifyContent: 'center',\n },\n rank: {\n fontWeight: '800',\n },\n suit: {\n fontWeight: '700',\n marginTop: -2,\n },\n});\n"]}
@@ -1,4 +1,21 @@
1
1
  import React from 'react';
2
2
  import type { TabletopTableProps } from './types';
3
+ /***
4
+ * Responsive tabletop surface for generic card-game and board-game scenes.
5
+ *
6
+ * Use `TabletopTable` to arrange seats around a themed table surface, display
7
+ * shared center cards, and show neutral seat labels/tokens without embedding game
8
+ * rules into the component.
9
+ *
10
+ * @readme
11
+ * @example Basic table
12
+ * ```tsx
13
+ * <TabletopTable
14
+ * seats={seats}
15
+ * centerCards={[{ rank: 'A', suit: 'spades' }]}
16
+ * centerLabel="Round 1"
17
+ * />
18
+ * ```
19
+ */
3
20
  export declare function TabletopTable({ seats, centerCards, centerLabel, centerSublabel, shape, seatCount, cardSize, disabled, colorScheme, accessibilityLabel, testID, }: TabletopTableProps): React.JSX.Element;
4
21
  //# sourceMappingURL=TabletopTable.d.ts.map
@@ -1 +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"}
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;;;;;;;;;;;;;;;;GAgBG;AACH,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"}
@@ -20,6 +20,23 @@ function createSeatAccessibilityLabel(seat) {
20
20
  parts.push('muted');
21
21
  return parts.join(', ');
22
22
  }
23
+ /***
24
+ * Responsive tabletop surface for generic card-game and board-game scenes.
25
+ *
26
+ * Use `TabletopTable` to arrange seats around a themed table surface, display
27
+ * shared center cards, and show neutral seat labels/tokens without embedding game
28
+ * rules into the component.
29
+ *
30
+ * @readme
31
+ * @example Basic table
32
+ * ```tsx
33
+ * <TabletopTable
34
+ * seats={seats}
35
+ * centerCards={[{ rank: 'A', suit: 'spades' }]}
36
+ * centerLabel="Round 1"
37
+ * />
38
+ * ```
39
+ */
23
40
  export function TabletopTable({ seats, centerCards = [], centerLabel, centerSublabel, shape = 'oval', seatCount, cardSize = 'small', disabled = false, colorScheme, accessibilityLabel, testID, }) {
24
41
  const { theme } = useZoraTheme();
25
42
  const colors = React.useMemo(() => createTabletopColorScheme(theme, colorScheme), [colorScheme, theme]);
@@ -1 +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.seatText }]}>\n {centerLabel}\n </Text>\n </View>\n ) : null}\n {centerSublabel !== undefined ? (\n <Text style={[styles.centerSublabel, { color: colors.tableMutedText }]}>\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.seatText }]}>{seat.label}</Text>\n {seat.sublabel !== undefined ? (\n <Text style={[styles.seatSublabel, { color: colors.seatMutedText }]}>\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: '700',\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: '700',\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"]}
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\n/***\n * Responsive tabletop surface for generic card-game and board-game scenes.\n *\n * Use `TabletopTable` to arrange seats around a themed table surface, display\n * shared center cards, and show neutral seat labels/tokens without embedding game\n * rules into the component.\n *\n * @readme\n * @example Basic table\n * ```tsx\n * <TabletopTable\n * seats={seats}\n * centerCards={[{ rank: 'A', suit: 'spades' }]}\n * centerLabel=\"Round 1\"\n * />\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.seatText }]}>\n {centerLabel}\n </Text>\n </View>\n ) : null}\n {centerSublabel !== undefined ? (\n <Text style={[styles.centerSublabel, { color: colors.tableMutedText }]}>\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.seatText }]}>{seat.label}</Text>\n {seat.sublabel !== undefined ? (\n <Text style={[styles.seatSublabel, { color: colors.seatMutedText }]}>\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: '700',\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: '700',\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"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora-tabletop",
3
3
  "type": "module",
4
- "version": "0.0.2",
4
+ "version": "0.0.4",
5
5
  "description": "Tabletop and card-game UI primitives for React Native and React Native Web, built on ZORA.",
6
6
  "homepage": "https://github.com/ankhorage/zora-tabletop#readme",
7
7
  "bugs": {
@@ -68,8 +68,8 @@
68
68
  },
69
69
  "devDependencies": {
70
70
  "@ankhorage/devtools": "^1.0.6",
71
- "@ankhorage/paradox": "^0.1.7",
72
- "@ankhorage/zora": "^2.5.1",
71
+ "@ankhorage/paradox": "^0.1.10",
72
+ "@ankhorage/zora": "^2.5.4",
73
73
  "@changesets/cli": "^2.31.0",
74
74
  "@types/bun": "^1.3.13",
75
75
  "@types/node": "^25.6.0",
package/src/colors.ts CHANGED
@@ -57,6 +57,19 @@ const DARK_TEXT_FALLBACK = '#111827';
57
57
  const LIGHT_TEXT_FALLBACK = '#ffffff';
58
58
  const MINIMUM_READABLE_CONTRAST = 4.5;
59
59
 
60
+ /***
61
+ * Creates the theme-derived color palette used by tabletop primitives.
62
+ *
63
+ * Use `createTabletopColorScheme` when custom components need to align with the
64
+ * same card, table, seat, token, and contrast-aware foreground colors as the
65
+ * built-in tabletop components.
66
+ *
67
+ * @readme
68
+ * @example Custom color scheme
69
+ * ```ts
70
+ * const colors = createTabletopColorScheme(theme, { tableFelt: '#065f46' });
71
+ * ```
72
+ */
60
73
  export function createTabletopColorScheme(
61
74
  theme: TabletopColorThemeShape,
62
75
  overrides: TabletopColorOverrides = {},
@@ -7,6 +7,18 @@ import { getTabletopCardDimensions } from '../../cardSizing';
7
7
  import { createTabletopColorScheme } from '../../colors';
8
8
  import type { CardBackProps } from './types';
9
9
 
10
+ /***
11
+ * Face-down playing-card primitive for hidden cards and decks.
12
+ *
13
+ * Use `CardBack` when a card should be represented visually without exposing its
14
+ * rank or suit. The component keeps a generic accessible label for hidden cards.
15
+ *
16
+ * @readme
17
+ * @example Hidden cards
18
+ * ```tsx
19
+ * <CardBack size="small" />
20
+ * ```
21
+ */
10
22
  export function CardBack({
11
23
  size = 'medium',
12
24
  muted = false,
@@ -9,6 +9,18 @@ function createFaceDownCards(count: number): readonly number[] {
9
9
  return Array.from({ length: Math.max(0, count) }, (_, index) => index);
10
10
  }
11
11
 
12
+ /***
13
+ * Compact row of visible and face-down playing cards.
14
+ *
15
+ * Use `CardHand` when a seat, pile, or custom layout needs to show multiple cards
16
+ * with consistent spacing, sizing, and muted state handling.
17
+ *
18
+ * @readme
19
+ * @example Mixed hand
20
+ * ```tsx
21
+ * <CardHand cards={[{ rank: 'Q', suit: 'hearts' }]} faceDownCards={1} />
22
+ * ```
23
+ */
12
24
  export function CardHand({
13
25
  cards = [],
14
26
  faceDownCards = 0,
@@ -19,6 +19,19 @@ function isRedSuit(suit: PlayingCardSuit): boolean {
19
19
  return suit === 'diamonds' || suit === 'hearts';
20
20
  }
21
21
 
22
+ /***
23
+ * Theme-aware face-up playing card primitive.
24
+ *
25
+ * Use `PlayingCard` for visible card values in hands, shared table cards, piles,
26
+ * or custom tabletop layouts. The component renders rank and suit text and exposes
27
+ * an accessible card label by default.
28
+ *
29
+ * @readme
30
+ * @example Face-up card
31
+ * ```tsx
32
+ * <PlayingCard card={{ rank: 'A', suit: 'spades' }} selected />
33
+ * ```
34
+ */
22
35
  export function PlayingCard({
23
36
  card,
24
37
  size = 'medium',
@@ -21,6 +21,23 @@ function createSeatAccessibilityLabel(seat: TabletopSeatState): string | undefin
21
21
  return parts.join(', ');
22
22
  }
23
23
 
24
+ /***
25
+ * Responsive tabletop surface for generic card-game and board-game scenes.
26
+ *
27
+ * Use `TabletopTable` to arrange seats around a themed table surface, display
28
+ * shared center cards, and show neutral seat labels/tokens without embedding game
29
+ * rules into the component.
30
+ *
31
+ * @readme
32
+ * @example Basic table
33
+ * ```tsx
34
+ * <TabletopTable
35
+ * seats={seats}
36
+ * centerCards={[{ rank: 'A', suit: 'spades' }]}
37
+ * centerLabel="Round 1"
38
+ * />
39
+ * ```
40
+ */
24
41
  export function TabletopTable({
25
42
  seats,
26
43
  centerCards = [],