playbook_ui 18.2.0.pre.rc.3 → 18.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_currency/_currency.tsx +3 -1
  3. data/app/pb_kits/playbook/pb_currency/kit.schema.json +1 -0
  4. data/app/pb_kits/playbook/pb_dashboard_value/_dashboard_value.tsx +3 -1
  5. data/app/pb_kits/playbook/pb_dashboard_value/kit.schema.json +1 -0
  6. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_highlight.jsx +101 -0
  7. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_highlight.md +3 -0
  8. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +1 -0
  9. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -1
  10. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.tsx +3 -1
  11. data/app/pb_kits/playbook/pb_icon_stat_value/kit.schema.json +1 -0
  12. data/app/pb_kits/playbook/pb_icon_value/_icon_value.tsx +3 -1
  13. data/app/pb_kits/playbook/pb_icon_value/kit.schema.json +1 -0
  14. data/app/pb_kits/playbook/pb_label_value/_label_value.tsx +3 -1
  15. data/app/pb_kits/playbook/pb_label_value/kit.schema.json +1 -0
  16. data/app/pb_kits/playbook/pb_message/_message.tsx +3 -1
  17. data/app/pb_kits/playbook/pb_message/kit.schema.json +1 -0
  18. data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.tsx +3 -1
  19. data/app/pb_kits/playbook/pb_multiple_users/kit.schema.json +1 -0
  20. data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.tsx +4 -2
  21. data/app/pb_kits/playbook/pb_multiple_users_stacked/kit.schema.json +1 -0
  22. data/app/pb_kits/playbook/pb_stat_value/_stat_value.tsx +3 -1
  23. data/app/pb_kits/playbook/pb_stat_value/kit.schema.json +1 -0
  24. data/app/pb_kits/playbook/pb_title_count/_title_count.tsx +3 -1
  25. data/app/pb_kits/playbook/pb_title_count/kit.schema.json +1 -0
  26. data/app/pb_kits/playbook/pb_title_detail/_title_detail.tsx +3 -1
  27. data/app/pb_kits/playbook/pb_title_detail/kit.schema.json +1 -0
  28. data/app/pb_kits/playbook/utilities/test/globalProps/onClick.test.js +227 -0
  29. data/dist/ai/all-schemas.json +11 -0
  30. data/dist/ai/forms.json +1 -1
  31. data/dist/ai/index.json +2 -2
  32. data/dist/ai/kits/currency.schema.json +1 -0
  33. data/dist/ai/kits/dashboard_value.schema.json +1 -0
  34. data/dist/ai/kits/icon_stat_value.schema.json +1 -0
  35. data/dist/ai/kits/icon_value.schema.json +1 -0
  36. data/dist/ai/kits/label_value.schema.json +1 -0
  37. data/dist/ai/kits/message.schema.json +1 -0
  38. data/dist/ai/kits/multiple_users.schema.json +1 -0
  39. data/dist/ai/kits/multiple_users_stacked.schema.json +1 -0
  40. data/dist/ai/kits/stat_value.schema.json +1 -0
  41. data/dist/ai/kits/title_count.schema.json +1 -0
  42. data/dist/ai/kits/title_detail.schema.json +1 -0
  43. data/dist/chunks/{_detail-Cy54syJC.js → _detail-Bsvl694i.js} +1 -1
  44. data/dist/chunks/_table-Bf6LGyL9.js +1 -0
  45. data/dist/chunks/{_typeahead-CXZH3KvV.js → _typeahead-w6S5Vx4b.js} +1 -1
  46. data/dist/chunks/vendor.js +2 -2
  47. data/dist/playbook-rails-react-bindings.js +1 -1
  48. data/dist/playbook-rails.js +1 -1
  49. data/lib/playbook/version.rb +1 -1
  50. metadata +8 -9
  51. data/dist/chunks/_table-BCqp1PAO.js +0 -1
@@ -7,12 +7,23 @@ import ButtonToolbar from '../../../pb_button_toolbar/_button_toolbar'
7
7
  import Caption from '../../../pb_caption/_caption'
8
8
  import Card from '../../../pb_card/_card'
9
9
  import Container from '../../../pb_container/_container'
10
+ import Currency from '../../../pb_currency/_currency'
11
+ import DashboardValue from '../../../pb_dashboard_value/_dashboard_value'
10
12
  import Detail from '../../../pb_detail/_detail'
11
13
  import Flex from '../../../pb_flex/_flex'
12
14
  import FormPill from '../../../pb_form_pill/_form_pill'
13
15
  import Highlight from '../../../pb_highlight/_highlight'
16
+ import IconStatValue from '../../../pb_icon_stat_value/_icon_stat_value'
17
+ import IconValue from '../../../pb_icon_value/_icon_value'
18
+ import LabelValue from '../../../pb_label_value/_label_value'
19
+ import Message from '../../../pb_message/_message'
20
+ import MultipleUsers from '../../../pb_multiple_users/_multiple_users'
21
+ import MultipleUsersStacked from '../../../pb_multiple_users_stacked/_multiple_users_stacked'
14
22
  import StarRating from '../../../pb_star_rating/_star_rating'
23
+ import StatValue from '../../../pb_stat_value/_stat_value'
15
24
  import Title from '../../../pb_title/_title'
25
+ import TitleCount from '../../../pb_title_count/_title_count'
26
+ import TitleDetail from '../../../pb_title_detail/_title_detail'
16
27
  import { globalProps } from '../../globalProps'
17
28
  import { globalEventProps } from '../../globalEventProps'
18
29
 
@@ -22,10 +33,21 @@ const optedInKits = [
22
33
  { Kit: Caption, name: 'Caption', extraProps: { text: 'Test' } },
23
34
  { Kit: Card, name: 'Card', extraProps: { children: 'Test' } },
24
35
  { Kit: Container, name: 'Container', extraProps: { children: 'Test' } },
36
+ { Kit: Currency, name: 'Currency', extraProps: { amount: '100.00', label: 'Total' } },
37
+ { Kit: DashboardValue, name: 'DashboardValue', extraProps: { statLabel: 'Sales', statValue: { value: 100 } } },
25
38
  { Kit: Detail, name: 'Detail', extraProps: { text: 'Test' } },
26
39
  { Kit: Flex, name: 'Flex', extraProps: { children: 'Test' } },
27
40
  { Kit: Highlight, name: 'Highlight', extraProps: { text: 'Test' } },
41
+ { Kit: IconStatValue, name: 'IconStatValue', extraProps: { icon: 'heart', text: 'Likes', value: 42 } },
42
+ { Kit: IconValue, name: 'IconValue', extraProps: { icon: 'heart', text: 'Favorites' } },
43
+ { Kit: LabelValue, name: 'LabelValue', extraProps: { label: 'Label', value: 'Value' } },
44
+ { Kit: Message, name: 'Message', extraProps: { label: 'Sender', message: 'Test' } },
45
+ { Kit: MultipleUsers, name: 'MultipleUsers', extraProps: { users: [{ name: 'Pat' }] } },
46
+ { Kit: MultipleUsersStacked, name: 'MultipleUsersStacked', extraProps: { users: [{ name: 'Pat' }] } },
47
+ { Kit: StatValue, name: 'StatValue', extraProps: { unit: 'mg', value: 100 } },
28
48
  { Kit: Title, name: 'Title', extraProps: { text: 'Test' } },
49
+ { Kit: TitleCount, name: 'TitleCount', extraProps: { count: 12, title: 'Items' } },
50
+ { Kit: TitleDetail, name: 'TitleDetail', extraProps: { detail: 'Detail', title: 'Title' } },
29
51
  ]
30
52
 
31
53
  describe('onClick GlobalEventProps', () => {
@@ -53,6 +75,7 @@ describe('onClick GlobalEventProps', () => {
53
75
  render(
54
76
  <Kit
55
77
  data={{ testid: testId }}
78
+ htmlOptions={{ 'data-testid': testId }}
56
79
  onClick={onClick}
57
80
  {...extraProps}
58
81
  />
@@ -219,4 +242,208 @@ describe('onClick GlobalEventProps', () => {
219
242
  expect(cardOnClick).toHaveBeenCalledTimes(1)
220
243
  })
221
244
  })
245
+
246
+ describe('value and summary kits fire once from nested regions', () => {
247
+ test('Currency label and value regions each invoke onClick once', () => {
248
+ const onClick = jest.fn()
249
+ const { container } = render(
250
+ <Currency
251
+ amount="42.00"
252
+ data={{ testid: 'onclick-currency-regions' }}
253
+ label="Balance"
254
+ onClick={onClick}
255
+ />
256
+ )
257
+
258
+ fireEvent.click(screen.getByText('Balance'))
259
+ fireEvent.click(container.querySelector('.pb_currency_value'))
260
+ expect(onClick).toHaveBeenCalledTimes(2)
261
+ })
262
+
263
+ test('Currency unstyled branch still attaches root onClick', () => {
264
+ const onClick = jest.fn()
265
+ render(
266
+ <Currency
267
+ amount="10.00"
268
+ data={{ testid: 'onclick-currency-unstyled' }}
269
+ label="Cash"
270
+ onClick={onClick}
271
+ unstyled
272
+ />
273
+ )
274
+
275
+ fireEvent.click(screen.getByTestId('onclick-currency-unstyled'))
276
+ expect(onClick).toHaveBeenCalledTimes(1)
277
+ })
278
+
279
+ test('LabelValue default and details variants fire once', () => {
280
+ const defaultOnClick = jest.fn()
281
+ const detailsOnClick = jest.fn()
282
+ render(
283
+ <>
284
+ <LabelValue
285
+ data={{ testid: 'onclick-label-value-default' }}
286
+ label="Status"
287
+ onClick={defaultOnClick}
288
+ value="Open"
289
+ />
290
+ <LabelValue
291
+ data={{ testid: 'onclick-label-value-details' }}
292
+ description="Meta"
293
+ icon="calendar"
294
+ label="Event"
295
+ onClick={detailsOnClick}
296
+ title="Kickoff"
297
+ variant="details"
298
+ />
299
+ </>
300
+ )
301
+
302
+ fireEvent.click(screen.getByText('Status'))
303
+ fireEvent.click(screen.getByText('Open'))
304
+ expect(defaultOnClick).toHaveBeenCalledTimes(2)
305
+
306
+ fireEvent.click(screen.getByText('Event'))
307
+ fireEvent.click(screen.getByText('Kickoff'))
308
+ expect(detailsOnClick).toHaveBeenCalledTimes(2)
309
+ })
310
+
311
+ test('IconStatValue icon and value regions fire once each', () => {
312
+ const onClick = jest.fn()
313
+ const { container } = render(
314
+ <IconStatValue
315
+ data={{ testid: 'onclick-icon-stat-value' }}
316
+ icon="heart"
317
+ onClick={onClick}
318
+ text="Likes"
319
+ value={7}
320
+ />
321
+ )
322
+
323
+ fireEvent.click(container.querySelector('[class*="pb_icon_circle_kit"]'))
324
+ fireEvent.click(screen.getByText('7'))
325
+ fireEvent.click(screen.getByText('Likes'))
326
+ expect(onClick).toHaveBeenCalledTimes(3)
327
+ })
328
+
329
+ test('DashboardValue nested StatValue does not duplicate the handler', () => {
330
+ const onClick = jest.fn()
331
+ render(
332
+ <DashboardValue
333
+ data={{ testid: 'onclick-dashboard-value' }}
334
+ onClick={onClick}
335
+ statLabel="Revenue"
336
+ statValue={{ unit: 'USD', value: 99 }}
337
+ />
338
+ )
339
+
340
+ fireEvent.click(screen.getByText('Revenue'))
341
+ fireEvent.click(screen.getByText('99'))
342
+ expect(onClick).toHaveBeenCalledTimes(2)
343
+ })
344
+ })
345
+
346
+ describe('whole-kit handlers preserve nested content behavior', () => {
347
+ test('Message nested content fires once with the Message root as currentTarget', () => {
348
+ const currentTargets = []
349
+ const onClick = jest.fn((event) => currentTargets.push(event.currentTarget))
350
+ render(
351
+ <Message
352
+ data={{ testid: 'onclick-message' }}
353
+ label="Sender"
354
+ message="Click this message"
355
+ onClick={onClick}
356
+ />
357
+ )
358
+
359
+ fireEvent.click(screen.getByText('Click this message'))
360
+
361
+ expect(onClick).toHaveBeenCalledTimes(1)
362
+ expect(currentTargets[0]).toBe(screen.getByTestId('onclick-message'))
363
+ })
364
+
365
+ test('Message child handlers still fire and bubble once to the Message root', () => {
366
+ const messageOnClick = jest.fn()
367
+ const buttonOnClick = jest.fn()
368
+ render(
369
+ <Message
370
+ label="Sender"
371
+ message="Message"
372
+ onClick={messageOnClick}
373
+ >
374
+ <Button
375
+ onClick={buttonOnClick}
376
+ text="Reply"
377
+ />
378
+ </Message>
379
+ )
380
+
381
+ fireEvent.click(screen.getByRole('button', { name: 'Reply' }))
382
+
383
+ expect(buttonOnClick).toHaveBeenCalledTimes(1)
384
+ expect(messageOnClick).toHaveBeenCalledTimes(1)
385
+ })
386
+
387
+ test('MultipleUsers tooltip avatar fires once with the kit root as currentTarget', () => {
388
+ const currentTargets = []
389
+ const onClick = jest.fn((event) => currentTargets.push(event.currentTarget))
390
+ render(
391
+ <MultipleUsers
392
+ data={{ testid: 'onclick-multiple-users' }}
393
+ onClick={onClick}
394
+ users={[{ imageUrl: 'pat.jpg', name: 'Pat', tooltip: 'Pat tooltip' }]}
395
+ withTooltip
396
+ />
397
+ )
398
+
399
+ fireEvent.click(screen.getByAltText('Pat'))
400
+
401
+ expect(onClick).toHaveBeenCalledTimes(1)
402
+ expect(currentTargets[0]).toBe(screen.getByTestId('onclick-multiple-users'))
403
+ })
404
+
405
+ test('MultipleUsers overflow count fires the whole-kit handler once', () => {
406
+ const onClick = jest.fn()
407
+ render(
408
+ <MultipleUsers
409
+ maxDisplayedUsers={2}
410
+ onClick={onClick}
411
+ users={[
412
+ { imageUrl: 'pat.jpg', name: 'Pat' },
413
+ { name: 'Sam' },
414
+ { name: 'Alex' },
415
+ ]}
416
+ />
417
+ )
418
+
419
+ fireEvent.click(screen.getByText('+2'))
420
+
421
+ expect(onClick).toHaveBeenCalledTimes(1)
422
+ })
423
+
424
+ test('MultipleUsersStacked avatar and overflow badge each fire once from the root', () => {
425
+ const currentTargets = []
426
+ const onClick = jest.fn((event) => currentTargets.push(event.currentTarget))
427
+ render(
428
+ <MultipleUsersStacked
429
+ data={{ testid: 'onclick-multiple-users-stacked' }}
430
+ onClick={onClick}
431
+ users={[
432
+ { imageUrl: 'pat.jpg', name: 'Pat' },
433
+ { name: 'Sam' },
434
+ { name: 'Alex' },
435
+ ]}
436
+ />
437
+ )
438
+
439
+ fireEvent.click(screen.getByAltText('Pat'))
440
+ fireEvent.click(screen.getByText('+2'))
441
+
442
+ expect(onClick).toHaveBeenCalledTimes(2)
443
+ expect(currentTargets).toEqual([
444
+ screen.getByTestId('onclick-multiple-users-stacked'),
445
+ screen.getByTestId('onclick-multiple-users-stacked'),
446
+ ])
447
+ })
448
+ })
222
449
  })
@@ -3778,6 +3778,7 @@
3778
3778
  }
3779
3779
  },
3780
3780
  "globalProps": true,
3781
+ "globalEventProps": true,
3781
3782
  "usage": {
3782
3783
  "react": {
3783
3784
  "import": "import { Currency } from 'playbook-ui'",
@@ -3838,6 +3839,7 @@
3838
3839
  }
3839
3840
  },
3840
3841
  "globalProps": true,
3842
+ "globalEventProps": true,
3841
3843
  "usage": {
3842
3844
  "react": {
3843
3845
  "import": "import { DashboardValue } from 'playbook-ui'",
@@ -7798,6 +7800,7 @@
7798
7800
  }
7799
7801
  },
7800
7802
  "globalProps": true,
7803
+ "globalEventProps": true,
7801
7804
  "usage": {
7802
7805
  "react": {
7803
7806
  "import": "import { IconStatValue } from 'playbook-ui'",
@@ -7857,6 +7860,7 @@
7857
7860
  }
7858
7861
  },
7859
7862
  "globalProps": true,
7863
+ "globalEventProps": true,
7860
7864
  "usage": {
7861
7865
  "react": {
7862
7866
  "import": "import { IconValue } from 'playbook-ui'",
@@ -8085,6 +8089,7 @@
8085
8089
  }
8086
8090
  },
8087
8091
  "globalProps": true,
8092
+ "globalEventProps": true,
8088
8093
  "usage": {
8089
8094
  "react": {
8090
8095
  "import": "import { LabelValue } from 'playbook-ui'",
@@ -8780,6 +8785,7 @@
8780
8785
  }
8781
8786
  },
8782
8787
  "globalProps": true,
8788
+ "globalEventProps": true,
8783
8789
  "usage": {
8784
8790
  "react": {
8785
8791
  "import": "import { Message } from 'playbook-ui'",
@@ -9243,6 +9249,7 @@
9243
9249
  }
9244
9250
  },
9245
9251
  "globalProps": true,
9252
+ "globalEventProps": true,
9246
9253
  "usage": {
9247
9254
  "react": {
9248
9255
  "import": "import { MultipleUsers } from 'playbook-ui'",
@@ -9308,6 +9315,7 @@
9308
9315
  }
9309
9316
  },
9310
9317
  "globalProps": true,
9318
+ "globalEventProps": true,
9311
9319
  "usage": {
9312
9320
  "react": {
9313
9321
  "import": "import { MultipleUsersStacked } from 'playbook-ui'",
@@ -12805,6 +12813,7 @@
12805
12813
  }
12806
12814
  },
12807
12815
  "globalProps": true,
12816
+ "globalEventProps": true,
12808
12817
  "usage": {
12809
12818
  "react": {
12810
12819
  "import": "import { StatValue } from 'playbook-ui'",
@@ -15065,6 +15074,7 @@
15065
15074
  }
15066
15075
  },
15067
15076
  "globalProps": true,
15077
+ "globalEventProps": true,
15068
15078
  "usage": {
15069
15079
  "react": {
15070
15080
  "import": "import { TitleCount } from 'playbook-ui'",
@@ -15118,6 +15128,7 @@
15118
15128
  }
15119
15129
  },
15120
15130
  "globalProps": true,
15131
+ "globalEventProps": true,
15121
15132
  "usage": {
15122
15133
  "react": {
15123
15134
  "import": "import { TitleDetail } from 'playbook-ui'",
data/dist/ai/forms.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "metadataVersion": 1,
3
- "version": "18.2.0-rc.3",
3
+ "version": "18.2.0",
4
4
  "builder": {
5
5
  "class": "Playbook::Forms::Builder",
6
6
  "helper": "pb_form_with",
data/dist/ai/index.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
- "version": "18.2.0-rc.3",
2
+ "version": "18.2.0",
3
3
  "metadataVersion": 1,
4
4
  "forms": "forms.json",
5
- "generated": "2026-10-20T17:53:24.606Z",
5
+ "generated": "2026-10-22T17:59:05.292Z",
6
6
  "schemas": {
7
7
  "globalProps": "global-props.schema.json",
8
8
  "globalEventProps": "global-event-props.schema.json",
@@ -137,6 +137,7 @@
137
137
  }
138
138
  },
139
139
  "globalProps": true,
140
+ "globalEventProps": true,
140
141
  "usage": {
141
142
  "react": {
142
143
  "import": "import { Currency } from 'playbook-ui'",
@@ -43,6 +43,7 @@
43
43
  }
44
44
  },
45
45
  "globalProps": true,
46
+ "globalEventProps": true,
46
47
  "usage": {
47
48
  "react": {
48
49
  "import": "import { DashboardValue } from 'playbook-ui'",
@@ -89,6 +89,7 @@
89
89
  }
90
90
  },
91
91
  "globalProps": true,
92
+ "globalEventProps": true,
92
93
  "usage": {
93
94
  "react": {
94
95
  "import": "import { IconStatValue } from 'playbook-ui'",
@@ -42,6 +42,7 @@
42
42
  }
43
43
  },
44
44
  "globalProps": true,
45
+ "globalEventProps": true,
45
46
  "usage": {
46
47
  "react": {
47
48
  "import": "import { IconValue } from 'playbook-ui'",
@@ -77,6 +77,7 @@
77
77
  }
78
78
  },
79
79
  "globalProps": true,
80
+ "globalEventProps": true,
80
81
  "usage": {
81
82
  "react": {
82
83
  "import": "import { LabelValue } from 'playbook-ui'",
@@ -94,6 +94,7 @@
94
94
  }
95
95
  },
96
96
  "globalProps": true,
97
+ "globalEventProps": true,
97
98
  "usage": {
98
99
  "react": {
99
100
  "import": "import { Message } from 'playbook-ui'",
@@ -60,6 +60,7 @@
60
60
  }
61
61
  },
62
62
  "globalProps": true,
63
+ "globalEventProps": true,
63
64
  "usage": {
64
65
  "react": {
65
66
  "import": "import { MultipleUsers } from 'playbook-ui'",
@@ -48,6 +48,7 @@
48
48
  }
49
49
  },
50
50
  "globalProps": true,
51
+ "globalEventProps": true,
51
52
  "usage": {
52
53
  "react": {
53
54
  "import": "import { MultipleUsersStacked } from 'playbook-ui'",
@@ -32,6 +32,7 @@
32
32
  }
33
33
  },
34
34
  "globalProps": true,
35
+ "globalEventProps": true,
35
36
  "usage": {
36
37
  "react": {
37
38
  "import": "import { StatValue } from 'playbook-ui'",
@@ -54,6 +54,7 @@
54
54
  }
55
55
  },
56
56
  "globalProps": true,
57
+ "globalEventProps": true,
57
58
  "usage": {
58
59
  "react": {
59
60
  "import": "import { TitleCount } from 'playbook-ui'",
@@ -36,6 +36,7 @@
36
36
  }
37
37
  },
38
38
  "globalProps": true,
39
+ "globalEventProps": true,
39
40
  "usage": {
40
41
  "react": {
41
42
  "import": "import { TitleDetail } from 'playbook-ui'",