@hjmds/react 1.46.1 → 1.48.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 (96) hide show
  1. package/dist/actions.d.ts +2 -2
  2. package/dist/activity-chip.d.ts +1 -1
  3. package/dist/advanced-display.d.ts +6 -0
  4. package/dist/advanced-display.d.ts.map +1 -1
  5. package/dist/advanced-display.js +4 -2
  6. package/dist/advanced-display.js.map +1 -1
  7. package/dist/advanced-forms.d.ts +2 -2
  8. package/dist/auth-screen.d.ts +1 -1
  9. package/dist/bottom-navigation.d.ts.map +1 -1
  10. package/dist/bottom-navigation.js +1 -1
  11. package/dist/bottom-navigation.js.map +1 -1
  12. package/dist/calendar.d.ts.map +1 -1
  13. package/dist/calendar.js +31 -24
  14. package/dist/calendar.js.map +1 -1
  15. package/dist/carousel.d.ts +5 -1
  16. package/dist/carousel.d.ts.map +1 -1
  17. package/dist/carousel.js +2 -2
  18. package/dist/carousel.js.map +1 -1
  19. package/dist/clipboard.d.ts +2 -2
  20. package/dist/color-picker.d.ts +33 -3
  21. package/dist/color-picker.d.ts.map +1 -1
  22. package/dist/color-picker.js +73 -10
  23. package/dist/color-picker.js.map +1 -1
  24. package/dist/communication.d.ts +6 -1
  25. package/dist/communication.d.ts.map +1 -1
  26. package/dist/communication.js +2 -2
  27. package/dist/communication.js.map +1 -1
  28. package/dist/conversation-row.d.ts +7 -1
  29. package/dist/conversation-row.d.ts.map +1 -1
  30. package/dist/conversation-row.js +4 -2
  31. package/dist/conversation-row.js.map +1 -1
  32. package/dist/date-range.d.ts +24 -3
  33. package/dist/date-range.d.ts.map +1 -1
  34. package/dist/date-range.js +38 -17
  35. package/dist/date-range.js.map +1 -1
  36. package/dist/display.d.ts +28 -0
  37. package/dist/display.d.ts.map +1 -1
  38. package/dist/display.js +11 -9
  39. package/dist/display.js.map +1 -1
  40. package/dist/evidence.d.ts +1 -1
  41. package/dist/evidence.js +1 -1
  42. package/dist/evidence.js.map +1 -1
  43. package/dist/feedback.d.ts +1 -1
  44. package/dist/floating-action-button.d.ts +1 -1
  45. package/dist/follow-list.d.ts +58 -0
  46. package/dist/follow-list.d.ts.map +1 -0
  47. package/dist/follow-list.js +25 -0
  48. package/dist/follow-list.js.map +1 -0
  49. package/dist/forms.d.ts +3 -3
  50. package/dist/image-viewer.d.ts +1 -1
  51. package/dist/index.d.ts +1 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/internal/calendar-paint.d.ts +12 -0
  55. package/dist/internal/calendar-paint.d.ts.map +1 -0
  56. package/dist/internal/calendar-paint.js +3 -0
  57. package/dist/internal/calendar-paint.js.map +1 -0
  58. package/dist/internal/identity-action.d.ts +12 -0
  59. package/dist/internal/identity-action.d.ts.map +1 -0
  60. package/dist/internal/identity-action.js +10 -0
  61. package/dist/internal/identity-action.js.map +1 -0
  62. package/dist/internal.d.ts +1 -1
  63. package/dist/layout.d.ts +1 -1
  64. package/dist/overlays.d.ts +4 -0
  65. package/dist/overlays.d.ts.map +1 -1
  66. package/dist/overlays.js +3 -3
  67. package/dist/overlays.js.map +1 -1
  68. package/dist/provider-button.d.ts +1 -1
  69. package/dist/public-exports.generated.d.ts +4 -0
  70. package/dist/public-exports.generated.d.ts.map +1 -1
  71. package/dist/public-exports.generated.js +12 -0
  72. package/dist/public-exports.generated.js.map +1 -1
  73. package/dist/screen-flows.d.ts +33 -4
  74. package/dist/screen-flows.d.ts.map +1 -1
  75. package/dist/screen-flows.js +25 -10
  76. package/dist/screen-flows.js.map +1 -1
  77. package/dist/screens.d.ts +38 -6
  78. package/dist/screens.d.ts.map +1 -1
  79. package/dist/screens.js +26 -12
  80. package/dist/screens.js.map +1 -1
  81. package/dist/selection.d.ts +1 -1
  82. package/dist/share-sheet.d.ts +65 -0
  83. package/dist/share-sheet.d.ts.map +1 -0
  84. package/dist/share-sheet.js +145 -0
  85. package/dist/share-sheet.js.map +1 -0
  86. package/dist/social-compositions.d.ts +10 -0
  87. package/dist/social-compositions.d.ts.map +1 -1
  88. package/dist/social-compositions.js +3 -2
  89. package/dist/social-compositions.js.map +1 -1
  90. package/dist/styles.css +122 -48
  91. package/dist/styles.layered.css +122 -48
  92. package/dist/table-family.js +1 -1
  93. package/dist/table-family.js.map +1 -1
  94. package/dist/toast.d.ts +1 -1
  95. package/dist/top-bar.d.ts +1 -1
  96. package/package.json +13 -3
@@ -1015,6 +1015,18 @@
1015
1015
  /* Product classification color (Badge categoryColor): the renderer resolves fill, ink and stroke per theme and checks AA. */
1016
1016
  .hjm-badge[data-tone="category"] { color: var(--hjm-badge-category-content); background: var(--hjm-badge-category-background); }
1017
1017
  .hjm-badge[data-variant="outline"][data-tone="category"] { background: transparent; border-color: var(--hjm-badge-category-border); }
1018
+
1019
+ /* Plain status badges keep semantic ink without a plate or outline. */
1020
+ .hjm-badge[data-variant="plain"] { background: transparent; border: 1px solid var(--hjm-color-border); color: var(--hjm-color-text-muted); }
1021
+ .hjm-badge[data-variant="plain"][data-tone="strong"] { color: var(--hjm-color-text); }
1022
+ .hjm-badge[data-variant="plain"][data-tone="brand"] { color: var(--hjm-color-content-brand); }
1023
+ .hjm-badge[data-variant="plain"][data-tone="danger"] { color: var(--hjm-color-danger); }
1024
+ .hjm-badge[data-variant="plain"][data-tone="info"] { background: transparent; color: var(--hjm-accent-info); border-color: color-mix(in srgb, var(--hjm-accent-info) 30%, transparent); }
1025
+ .hjm-badge[data-variant="plain"][data-tone="success"] { background: transparent; color: var(--hjm-accent-success); border-color: color-mix(in srgb, var(--hjm-accent-success) 30%, transparent); }
1026
+ .hjm-badge[data-variant="plain"][data-tone="warning"] { background: transparent; color: var(--hjm-accent-warning); border-color: color-mix(in srgb, var(--hjm-accent-warning) 30%, transparent); }
1027
+ .hjm-badge[data-variant="plain"][data-tone="attention"] { background: transparent; color: var(--hjm-accent-attention); border-color: color-mix(in srgb, var(--hjm-accent-attention) 30%, transparent); }
1028
+ .hjm-badge[data-variant="plain"][data-tone="category"] { background: transparent; border-color: var(--hjm-badge-category-border); }
1029
+ .hjm-badge[data-variant="plain"] { border: 0; }
1018
1030
  .hjm-tag[data-tone="info"] { color: var(--hjm-accent-info); background: color-mix(in srgb, var(--hjm-accent-info) 14%, transparent); border-color: color-mix(in srgb, var(--hjm-accent-info) 30%, transparent); }
1019
1031
  .hjm-tag[data-tone="success"] { color: var(--hjm-accent-success); background: color-mix(in srgb, var(--hjm-accent-success) 14%, transparent); border-color: color-mix(in srgb, var(--hjm-accent-success) 30%, transparent); }
1020
1032
  .hjm-tag[data-tone="attention"] { color: var(--hjm-accent-attention); background: color-mix(in srgb, var(--hjm-accent-attention) 14%, transparent); border-color: color-mix(in srgb, var(--hjm-accent-attention) 30%, transparent); }
@@ -1052,8 +1064,8 @@
1052
1064
  .hjm-card__header-actions { position: relative; z-index: 1; display: flex; flex: 0 0 auto; align-items: center; gap: var(--hjm-space-xs); }
1053
1065
  .hjm-card__leading { flex: 0 0 auto; display: inline-grid; place-items: center; line-height: 1; }
1054
1066
  .hjm-card__copy { flex: 1 1 auto; min-inline-size: 0; display: grid; gap: var(--hjm-space-xs); }
1055
- /* cardRecipe.title.emphasis "strong": without a weight the h2–h6 element fell back to the UA bold (700). */
1056
- .hjm-card__title { margin: 0; color: var(--hjm-color-text); font-size: var(--hjm-type-title-size); line-height: var(--hjm-type-title-line-height); font-weight: var(--hjm-text-emphasis-strong); overflow-wrap: anywhere; }
1067
+ /* Follow cardRecipe.title: native headings must not fall back to the UA bold weight. */
1068
+ .hjm-card__title { margin: 0; color: var(--hjm-color-text); font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); font-weight: var(--hjm-text-emphasis-medium); overflow-wrap: anywhere; }
1057
1069
  .hjm-card__description { margin: 0; overflow-wrap: anywhere; }
1058
1070
  .hjm-card__actions { display: flex; flex-wrap: wrap; gap: var(--hjm-space-xs); padding: 0 var(--hjm-space-md) var(--hjm-space-md); }
1059
1071
  /* Row rhythm reads the recipe density variables so the stylesheet does not
@@ -1119,7 +1131,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1119
1131
  .hjm-section__copy { display: grid; flex: 1 1 auto; gap: var(--hjm-space-xxs); min-inline-size: 0; }
1120
1132
  /* sectionRecipe.title is the `title` variant (18/26 bold) and description the `caption` variant (11/16), as Native draws them.
1121
1133
  Until 2026-10-06 Web inherited body (14) for both, so the same Section header was smaller on Web. */
1122
- .hjm-section__title { margin: 0; color: var(--hjm-color-text-body); font-size: var(--hjm-type-title-size); line-height: var(--hjm-type-title-line-height); font-weight: var(--hjm-type-title-weight); overflow-wrap: anywhere; }
1134
+ .hjm-section__title { margin: 0; color: var(--hjm-color-text-body); font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); font-weight: var(--hjm-type-title-weight); overflow-wrap: anywhere; }
1123
1135
  .hjm-section__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); overflow-wrap: anywhere; }
1124
1136
  .hjm-section__action { flex: 0 0 auto; }
1125
1137
  .hjm-section__content { min-inline-size: 0; }
@@ -1184,7 +1196,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1184
1196
  .hjm-statistic__label { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); font-weight: var(--hjm-text-emphasis-medium); overflow-wrap: anywhere; }
1185
1197
  .hjm-statistic[data-density="compact"] .hjm-statistic__label { font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
1186
1198
  .hjm-statistic__value-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--hjm-space-xxs); min-inline-size: 0; }
1187
- .hjm-statistic__value { color: var(--hjm-statistic-value-color, var(--hjm-color-text)); font-size: var(--hjm-type-heading-size); line-height: var(--hjm-type-heading-line-height); font-weight: var(--hjm-font-weight-semibold); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1199
+ .hjm-statistic__value { color: var(--hjm-statistic-value-color, var(--hjm-color-text)); font-size: var(--hjm-type-title-size); line-height: var(--hjm-type-title-line-height); font-weight: var(--hjm-font-weight-semibold); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1188
1200
  .hjm-statistic[data-density="compact"] .hjm-statistic__value { font-size: var(--hjm-type-body-large-size); line-height: var(--hjm-type-body-large-line-height); }
1189
1201
  .hjm-statistic__affix { color: var(--hjm-color-text-body); font-size: var(--hjm-type-body-size); line-height: var(--hjm-type-body-line-height); font-weight: var(--hjm-text-emphasis-medium); }
1190
1202
  .hjm-statistic__hint { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
@@ -1197,14 +1209,16 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1197
1209
  .hjm-statistic-group { grid-template-columns: minmax(0, 1fr); }
1198
1210
  }
1199
1211
 
1200
- .hjm-notice { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hjm-space-sm); padding: var(--hjm-space-md); border: 1px solid; border-radius: var(--hjm-radius-md); color: var(--hjm-color-text-body); background: var(--hjm-color-bg); border-color: var(--hjm-color-border); }
1201
- .hjm-notice[data-tone="info"] { border-color: var(--hjm-accent-info); }
1202
- .hjm-notice[data-tone="success"] { border-color: var(--hjm-accent-success); background: color-mix(in srgb, var(--hjm-accent-success) 10%, var(--hjm-color-bg)); }
1203
- .hjm-notice[data-tone="warning"] { border-color: var(--hjm-accent-warning); background: color-mix(in srgb, var(--hjm-accent-warning) 10%, var(--hjm-color-bg)); }
1204
- .hjm-notice[data-tone="attention"] { border-color: var(--hjm-accent-attention); background: color-mix(in srgb, var(--hjm-accent-attention) 10%, var(--hjm-color-bg)); }
1205
- .hjm-notice[data-tone="danger"] { border-color: var(--hjm-color-danger); background: color-mix(in srgb, var(--hjm-color-danger) 10%, var(--hjm-color-bg)); }
1212
+ /* noticeRecipe 2026-10-25: no outline; tone lives in the tint, the leading accentBar and the icon. The bar is
1213
+ positioned in the padding so it spans the whole notice even when the action wraps to a second line. */
1214
+ .hjm-notice { --hjm-notice-accent: var(--hjm-accent-info); position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--hjm-space-sm); padding: var(--hjm-space-md); padding-inline-start: calc(var(--hjm-space-md) + 4px + var(--hjm-space-sm)); border-radius: var(--hjm-radius-md); color: var(--hjm-color-text-body); background: var(--hjm-color-surface-alt); }
1215
+ .hjm-notice[data-appearance="panel"]::before { content: ""; position: absolute; inset-block: var(--hjm-space-md); inset-inline-start: var(--hjm-space-md); inline-size: 4px; border-radius: var(--hjm-radius-full); background: var(--hjm-notice-accent); }
1216
+ .hjm-notice[data-tone="success"] { --hjm-notice-accent: var(--hjm-accent-success); background: color-mix(in srgb, var(--hjm-accent-success) 10%, var(--hjm-color-bg)); }
1217
+ .hjm-notice[data-tone="warning"] { --hjm-notice-accent: var(--hjm-accent-warning); background: color-mix(in srgb, var(--hjm-accent-warning) 10%, var(--hjm-color-bg)); }
1218
+ .hjm-notice[data-tone="attention"] { --hjm-notice-accent: var(--hjm-accent-attention); background: color-mix(in srgb, var(--hjm-accent-attention) 10%, var(--hjm-color-bg)); }
1219
+ .hjm-notice[data-tone="danger"] { --hjm-notice-accent: var(--hjm-color-danger); background: color-mix(in srgb, var(--hjm-color-danger) 10%, var(--hjm-color-bg)); }
1206
1220
  /* Status is placed inside the saved card/form; Badge carries tone without a second surface. */
1207
- .hjm-notice[data-appearance="status"] { padding: 0; border: 0; background: transparent; }
1221
+ .hjm-notice[data-appearance="status"] { padding: 0; background: transparent; }
1208
1222
  .hjm-notice[data-appearance="status"] .hjm-notice__content { justify-items: start; }
1209
1223
  /* Reserve readable copy; wrap the action instead of crushing its label. */
1210
1224
  .hjm-notice__content { flex: 1 1 60%; min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
@@ -1214,7 +1228,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1214
1228
  .hjm-notice__action { flex: 0 0 auto; max-inline-size: 100%; }
1215
1229
  .hjm-notice__title, .hjm-notice__description { overflow-wrap: anywhere; }
1216
1230
  /* noticeRecipe/emptyStateRecipe title weight; the <strong> otherwise draws the UA bold (700). */
1217
- .hjm-notice__title { font-weight: var(--hjm-type-title-weight); }
1231
+ .hjm-notice__title { font-weight: var(--hjm-type-title-weight); color: var(--hjm-color-text); }
1218
1232
 
1219
1233
  /* emptyStateRecipe.density.regular paddingVertical xxxl 40 (2026-10-06; Web had xxl 32, Native read the recipe). */
1220
1234
  /* Like Native, a regular empty state fills the rest of a flex host and centers in it; compact (cards, sheets) stays content-high. */
@@ -1470,8 +1484,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1470
1484
  .hjm-line-score__table .hjm-line-score__team { inset-inline-start: 0; }
1471
1485
  .hjm-line-score__table td.hjm-line-score__period { min-inline-size: 26px; color: var(--hjm-color-text-sub); }
1472
1486
  .hjm-line-score__table td[data-scored] { color: var(--hjm-color-text); font-weight: var(--hjm-text-emphasis-medium); }
1473
- .hjm-line-score__table [data-current] { background: var(--hjm-table-family-selected); }
1474
- .hjm-line-score__table th[data-current] { color: var(--hjm-color-content-brand); }
1487
+ .hjm-line-score__table [data-current] { background: var(--hjm-line-score-current-background); }
1488
+ .hjm-line-score__table th[data-current] { color: var(--hjm-line-score-current-color); }
1475
1489
  .hjm-line-score__total { inline-size: var(--hjm-line-score-total-width); min-inline-size: var(--hjm-line-score-total-width); color: var(--hjm-color-text-muted); font-weight: var(--hjm-text-emphasis-medium); }
1476
1490
  /* A collapsed-table border stays with the table, not the pinned cell, so the edge is an inset shadow. */
1477
1491
  .hjm-line-score__total-edge { box-shadow: inset 1px 0 0 var(--hjm-color-border); }
@@ -1732,18 +1746,29 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1732
1746
  */
1733
1747
  /* Each hit/hover layer belongs to its own day. Without this containing block
1734
1748
  the last absolute layer covered the whole preview and stole pointer clicks. */
1749
+ /* dateRangeRecipe 2026-10-25: one band between two filled edges (Material 3/Airbnb motif) instead of an underline and
1750
+ outlines; the band is as tall as the date circle and rounds off where a week row starts or ends. */
1751
+ .hjm-date-range { display: grid; gap: var(--hjm-space-md); }
1735
1752
  .hjm-date-range .hjm-calendar__day { position: relative; isolation: isolate; }
1736
1753
  .hjm-date-range .hjm-calendar__day-label { position: relative; z-index: 1; pointer-events: none; }
1737
- .hjm-date-range__cell { position: absolute; inset: 0; border-radius: var(--hjm-radius-sm); pointer-events: auto; }
1738
- .hjm-date-range__cell[data-range="between"] { box-shadow: inset 0 -2px var(--hjm-color-content-brand); background: var(--hjm-color-bg); }
1739
- .hjm-date-range__cell[data-range="start"],
1740
- .hjm-date-range__cell[data-range="end"] { background: var(--hjm-color-bg); outline: 2px solid var(--hjm-color-focus); }
1741
- .hjm-date-range__cell[data-range="none"] { background: transparent; }
1754
+ .hjm-calendar__band { position: absolute; inset-block-start: 0; inset-inline: 0; block-size: var(--hjm-calendar-indicator-size, var(--hjm-calendar-cell-size)); background: color-mix(in srgb, var(--hjm-color-primary) 15%, transparent); pointer-events: none; }
1755
+ .hjm-calendar__day[data-range-band="toEnd"] .hjm-calendar__band { inset-inline-start: 50%; }
1756
+ .hjm-calendar__day[data-range-band="toStart"] .hjm-calendar__band { inset-inline-end: 50%; }
1757
+ .hjm-calendar__day:first-child:not([data-range-band="toEnd"]) .hjm-calendar__band { border-start-start-radius: var(--hjm-radius-full); border-end-start-radius: var(--hjm-radius-full); }
1758
+ .hjm-calendar__day:last-child:not([data-range-band="toStart"]) .hjm-calendar__band { border-start-end-radius: var(--hjm-radius-full); border-end-end-radius: var(--hjm-radius-full); }
1759
+ .hjm-calendar__day[data-today][data-selected] .hjm-calendar__day-label { border-color: transparent; }
1760
+ .hjm-date-range__presets { display: flex; flex-wrap: wrap; gap: var(--hjm-space-xs); }
1761
+ .hjm-date-range__summary { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--hjm-space-xs); }
1762
+ .hjm-date-range__field { display: grid; gap: var(--hjm-space-xxs); min-inline-size: 0; padding: var(--hjm-space-xs) var(--hjm-space-sm); border: 2px solid transparent; border-radius: var(--hjm-radius-md); background: var(--hjm-color-surface-alt); }
1763
+ .hjm-date-range__field[data-active] { border-color: var(--hjm-color-primary); }
1764
+ .hjm-date-range__field-label { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); }
1765
+ .hjm-date-range__field-value { overflow: hidden; color: var(--hjm-color-text); font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; }
1766
+ .hjm-date-range__field[data-empty] .hjm-date-range__field-value { color: var(--hjm-color-text-sub); }
1742
1767
 
1743
1768
  /* AvatarGroup: overlap comes from the recipe ratio, not a per-size pixel value. */
1744
1769
  .hjm-avatar-group { display: inline-flex; align-items: center; }
1745
1770
  .hjm-avatar-group > * + * { margin-inline-start: calc(var(--hjm-avatar-overlap) * -1); }
1746
- .hjm-avatar-group > .hjm-avatar { border: 2px solid var(--hjm-color-bg); border-radius: var(--hjm-radius-full); }
1771
+ .hjm-avatar-group > .hjm-avatar, .hjm-avatar-group > .hjm-identity-action .hjm-avatar { border: 2px solid var(--hjm-color-bg); border-radius: var(--hjm-radius-full); }
1747
1772
  .hjm-avatar-group__overflow {
1748
1773
  display: grid;
1749
1774
  place-items: center;
@@ -1776,7 +1801,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1776
1801
  font-family: var(--hjm-font-family-code, ui-monospace, SFMono-Regular, Consolas, monospace);
1777
1802
  }
1778
1803
  .hjm-text-format[data-kind="kbd"] {
1779
- border: 1px solid var(--hjm-color-border);
1804
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
1780
1805
  color: var(--hjm-color-text-body);
1781
1806
  font-size: var(--hjm-type-label-size);
1782
1807
  }
@@ -2091,7 +2116,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2091
2116
  max-block-size: 12rem;
2092
2117
  margin: var(--hjm-space-xxs) 0 0;
2093
2118
  padding: var(--hjm-space-xxs);
2094
- border: 1px solid var(--hjm-color-border);
2119
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
2095
2120
  border-radius: var(--hjm-radius-md);
2096
2121
  background: var(--hjm-color-bg);
2097
2122
  list-style: none;
@@ -2579,7 +2604,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2579
2604
  block-size: 100dvh;
2580
2605
  min-inline-size: 0;
2581
2606
  overflow: hidden;
2582
- border: 1px solid var(--hjm-color-border);
2607
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
2583
2608
  border-radius: 0;
2584
2609
  color: var(--hjm-color-text);
2585
2610
  background: var(--hjm-color-bg);
@@ -2653,7 +2678,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2653
2678
  overscroll-behavior: contain;
2654
2679
  box-sizing: border-box;
2655
2680
  padding: var(--hjm-space-md);
2656
- border: 1px solid var(--hjm-color-border);
2681
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
2657
2682
  border-radius: var(--hjm-radius-md);
2658
2683
  color: var(--hjm-color-text);
2659
2684
  background: var(--hjm-color-bg);
@@ -2696,7 +2721,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2696
2721
  /* menuRecipe.surface (floatingSurfaceContract) padding spacing.xs 8. Until 2026-10-06 Web drew 4 here and in the
2697
2722
  Select/Combobox/ContextMenu popups that share the same surface contract. */
2698
2723
  padding: var(--hjm-menu-padding, var(--hjm-space-xs));
2699
- border: 1px solid var(--hjm-color-border);
2724
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
2700
2725
  border-radius: var(--hjm-radius-md);
2701
2726
  background: var(--hjm-color-bg);
2702
2727
  box-shadow: var(--hjm-shadow-floating);
@@ -2768,7 +2793,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2768
2793
  .hjm-select__indicator { flex: 0 0 auto; color: var(--hjm-color-text-muted); pointer-events: none; }
2769
2794
  .hjm-select__busy-indicator { flex: 0 0 auto; inline-size: 1em; block-size: 1em; border: 2px solid var(--hjm-color-content-brand); border-inline-end-color: transparent; border-radius: 50%; animation: hjm-spin 800ms linear infinite; }
2770
2795
  .hjm-select__native + .hjm-select__indicator { margin-inline-start: calc(-1 * var(--hjm-space-lg)); }
2771
- .hjm-select__listbox { position: fixed; z-index: var(--hjm-layer-dropdown); max-inline-size: min(26.25rem, calc(100vw - (2 * var(--hjm-space-md)))); max-block-size: 22.5rem; overflow: auto; padding: var(--hjm-select-popover-padding, var(--hjm-space-xs)); /* selectRecipe.popover.padding 8 (was 4 until 2026-10-06) */ border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); background: var(--hjm-color-bg); box-shadow: var(--hjm-shadow-floating); }
2796
+ .hjm-select__listbox { position: fixed; z-index: var(--hjm-layer-dropdown); max-inline-size: min(26.25rem, calc(100vw - (2 * var(--hjm-space-md)))); max-block-size: 22.5rem; overflow: auto; padding: var(--hjm-select-popover-padding, var(--hjm-space-xs)); /* selectRecipe.popover.padding 8 (was 4 until 2026-10-06) */ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent); border-radius: var(--hjm-radius-md); background: var(--hjm-color-bg); box-shadow: var(--hjm-shadow-floating); }
2772
2797
  .hjm-select__section-label { padding: var(--hjm-space-xs) var(--hjm-space-sm); color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); font-weight: var(--hjm-text-emphasis-medium); }
2773
2798
  .hjm-select__option, .hjm-select__message { min-block-size: var(--hjm-control-min-touch-target); display: flex; align-items: center; gap: var(--hjm-space-sm); padding: var(--hjm-space-xs) var(--hjm-space-sm); border-radius: var(--hjm-radius-sm); overflow-wrap: anywhere; }
2774
2799
  .hjm-select[data-density="comfortable"] .hjm-select__option,
@@ -2798,7 +2823,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2798
2823
  max-block-size: 22.5rem;
2799
2824
  overflow: auto;
2800
2825
  padding: var(--hjm-combobox-popover-padding, var(--hjm-space-xs)); /* comboboxRecipe.popover = selectRecipe.popover, 8 (was 4 until 2026-10-06) */
2801
- border: 1px solid var(--hjm-color-border);
2826
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
2802
2827
  border-radius: var(--hjm-radius-md);
2803
2828
  background: var(--hjm-color-bg);
2804
2829
  box-shadow: var(--hjm-shadow-floating);
@@ -2884,7 +2909,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2884
2909
  place-items: center;
2885
2910
  inline-size: var(--hjm-avatar-size, 2.5rem);
2886
2911
  block-size: var(--hjm-avatar-size, 2.5rem);
2887
- border: 1px solid var(--hjm-color-border);
2912
+ border: 1px solid color-mix(in srgb, var(--hjm-color-border-control) 50%, transparent);
2888
2913
  border-radius: 50%;
2889
2914
  color: var(--hjm-color-text-muted);
2890
2915
  background: var(--hjm-color-bg);
@@ -3341,25 +3366,40 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3341
3366
  .hjm-menu-morph__item[data-tone="danger"] { color: var(--hjm-color-danger); }
3342
3367
  .hjm-menu-morph__item:disabled { opacity: 0.5; cursor: not-allowed; }
3343
3368
 
3344
- /* Selected colors are user data; control surfaces keep the same canvas tokens as other inputs. */
3345
- .hjm-color-picker { border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); background: var(--hjm-color-bg); color: var(--hjm-color-text); padding: 1rem; margin: 0; min-inline-size: 0; overflow-wrap: anywhere; }
3346
- .hjm-color-picker legend { max-inline-size: 100%; overflow-wrap: anywhere; }
3347
- .hjm-color-picker__row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
3348
- .hjm-color-picker label { display: flex; flex-direction: column; gap: 0.5rem; min-inline-size: 0; }
3349
- .hjm-color-picker__hex { flex: 1 1 10rem; }
3350
- .hjm-color-picker input { box-sizing: border-box; min-block-size: var(--hjm-color-picker-target); min-inline-size: 0; max-inline-size: 100%; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); background: var(--hjm-color-bg); color: var(--hjm-color-text); font: inherit; }
3351
- .hjm-color-picker input[type="text"] { inline-size: 100%; padding-inline: 0.5rem; }
3352
- .hjm-color-picker input[type="color"] { inline-size: 3rem; padding: 0.25rem; }
3353
- .hjm-color-picker__opacity { margin-block-start: 0.75rem; }
3354
- .hjm-color-picker__opacity input[type="range"] { accent-color: var(--hjm-color-primary); }
3355
- .hjm-color-picker__preview { block-size: 1.5rem; margin-block-start: 0.75rem; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); }
3356
- .hjm-color-picker__presets { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-block-start: 0.75rem; }
3357
- .hjm-color-picker__presets button { display: inline-flex; align-items: center; gap: 0.5rem; min-block-size: var(--hjm-color-picker-target); max-inline-size: 100%; overflow-wrap: anywhere; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); padding: 0.5rem; background: var(--hjm-color-bg); color: var(--hjm-color-text); font: inherit; cursor: pointer; }
3358
- .hjm-color-picker__presets button[aria-pressed="true"] { border-color: var(--hjm-color-primary); }
3359
- .hjm-color-picker__swatch { inline-size: 1rem; block-size: 1rem; flex-shrink: 0; border: 1px solid var(--hjm-color-border); }
3360
- .hjm-color-picker :is(input, button):focus-visible { outline: 2px solid var(--hjm-color-primary); outline-offset: 2px; }
3361
- .hjm-color-picker__error { color: var(--hjm-color-danger); margin-block: 0.5rem; }
3369
+ /* Selected colors are user data; control surfaces keep the same canvas tokens as other inputs. The 2026-10-25 redesign
3370
+ edits HSV: a saturation/brightness area over the hue colour, then hue and opacity bars (Figma/Procreate Classic). */
3371
+ .hjm-color-picker { --hjm-color-picker-checker: repeating-conic-gradient(#d6d6d6 0% 25%, #ffffff 0% 50%) 0 0 / 12px 12px; display: grid; gap: var(--hjm-space-md); border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); background: var(--hjm-color-bg); color: var(--hjm-color-text); padding: 1rem; margin: 0; min-inline-size: 0; overflow-wrap: anywhere; }
3372
+ .hjm-color-picker legend { max-inline-size: 100%; overflow-wrap: anywhere; padding-inline: 0.25rem; }
3373
+ .hjm-color-picker__area { position: relative; aspect-ratio: var(--hjm-color-picker-area-ratio); border-radius: var(--hjm-radius-md); background: linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent), var(--hjm-color-picker-hue); touch-action: none; cursor: crosshair; user-select: none; }
3374
+ .hjm-color-picker__area[data-disabled] { cursor: not-allowed; }
3375
+ .hjm-color-picker__area:focus-within { outline: var(--hjm-focus-width, 2px) solid var(--hjm-color-focus); outline-offset: 2px; }
3376
+ .hjm-color-picker__area-thumb { position: absolute; inline-size: var(--hjm-color-picker-area-thumb); block-size: var(--hjm-color-picker-area-thumb); box-sizing: border-box; translate: -50% -50%; border: 3px solid #fff; border-radius: 50%; background: var(--hjm-color-picker-opaque); box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3), 0 1px 4px rgb(0 0 0 / 0.35); pointer-events: none; }
3377
+ .hjm-color-picker__bar { appearance: none; -webkit-appearance: none; display: block; inline-size: 100%; block-size: var(--hjm-color-picker-target); margin: 0; background: transparent; cursor: pointer; }
3378
+ .hjm-color-picker__bar::-webkit-slider-runnable-track { block-size: var(--hjm-color-picker-bar); border-radius: 999px; background: var(--hjm-color-picker-bar-fill); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.12); }
3379
+ .hjm-color-picker__bar::-moz-range-track { block-size: var(--hjm-color-picker-bar); border-radius: 999px; background: var(--hjm-color-picker-bar-fill); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.12); }
3380
+ .hjm-color-picker__bar::-webkit-slider-thumb { -webkit-appearance: none; inline-size: var(--hjm-color-picker-bar-thumb); block-size: var(--hjm-color-picker-bar-thumb); margin-block-start: calc((var(--hjm-color-picker-bar) - var(--hjm-color-picker-bar-thumb)) / 2); box-sizing: border-box; border: 3px solid #fff; border-radius: 50%; background: var(--hjm-color-picker-bar-thumb-fill); box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3), 0 1px 4px rgb(0 0 0 / 0.35); }
3381
+ .hjm-color-picker__bar::-moz-range-thumb { inline-size: var(--hjm-color-picker-bar-thumb); block-size: var(--hjm-color-picker-bar-thumb); box-sizing: border-box; border: 3px solid #fff; border-radius: 50%; background: var(--hjm-color-picker-bar-thumb-fill); box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3), 0 1px 4px rgb(0 0 0 / 0.35); }
3382
+ .hjm-color-picker__bar--hue { --hjm-color-picker-bar-fill: var(--hjm-color-picker-hue-gradient); --hjm-color-picker-bar-thumb-fill: var(--hjm-color-picker-hue); }
3383
+ .hjm-color-picker__bar--alpha { --hjm-color-picker-bar-fill: linear-gradient(to right, transparent, var(--hjm-color-picker-opaque)), var(--hjm-color-picker-checker); --hjm-color-picker-bar-thumb-fill: linear-gradient(var(--hjm-color-picker-current), var(--hjm-color-picker-current)), var(--hjm-color-picker-checker); }
3384
+ .hjm-color-picker__bar:focus-visible { outline: var(--hjm-focus-width, 2px) solid var(--hjm-color-focus); outline-offset: 2px; border-radius: 999px; }
3385
+ .hjm-color-picker__row { display: flex; align-items: flex-end; gap: 0.75rem; }
3386
+ .hjm-color-picker__preview { flex-shrink: 0; inline-size: var(--hjm-color-picker-preview); block-size: var(--hjm-color-picker-preview); border-radius: 50%; background: linear-gradient(var(--hjm-color-picker-current), var(--hjm-color-picker-current)), var(--hjm-color-picker-checker); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15); }
3387
+ .hjm-color-picker__hex { display: flex; flex: 1 1 8rem; flex-direction: column; gap: 0.25rem; min-inline-size: 0; }
3388
+ .hjm-color-picker__hex input { box-sizing: border-box; inline-size: 100%; min-block-size: var(--hjm-color-picker-target); padding-inline: 0.5rem; border: 1px solid var(--hjm-color-border); border-radius: var(--hjm-radius-md); background: var(--hjm-color-bg); color: var(--hjm-color-text); font: inherit; font-variant-numeric: tabular-nums; }
3389
+ .hjm-color-picker__hex input:focus-visible { outline: var(--hjm-focus-width, 2px) solid var(--hjm-color-focus); outline-offset: 2px; }
3390
+ .hjm-color-picker__opacity { min-block-size: var(--hjm-color-picker-target); display: inline-flex; align-items: center; font-variant-numeric: tabular-nums; color: var(--hjm-color-text-muted, inherit); }
3391
+ .hjm-color-picker__error { color: var(--hjm-color-danger); margin: 0; }
3362
3392
  .hjm-color-picker:disabled { opacity: 0.5; }
3393
+ .hjm-color-picker:disabled .hjm-color-picker__bar { cursor: not-allowed; }
3394
+ .hjm-color-swatches { border: 0; margin: 0; padding: 0; min-inline-size: 0; }
3395
+ .hjm-color-swatches legend { padding: 0; margin-block-end: 0.5rem; }
3396
+ .hjm-color-swatches__list { display: flex; flex-wrap: wrap; gap: 0.25rem; }
3397
+ .hjm-color-swatches[data-layout="scroll"] .hjm-color-swatches__list { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; }
3398
+ .hjm-color-swatches__item { position: relative; display: inline-grid; place-items: center; flex-shrink: 0; inline-size: var(--hjm-color-swatch-target); block-size: var(--hjm-color-swatch-target); cursor: pointer; }
3399
+ .hjm-color-swatches__swatch { inline-size: var(--hjm-color-swatch-size); block-size: var(--hjm-color-swatch-size); border-radius: 50%; background: linear-gradient(var(--hjm-color-swatch), var(--hjm-color-swatch)), repeating-conic-gradient(#d6d6d6 0% 25%, #ffffff 0% 50%) 0 0 / 10px 10px; box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15); }
3400
+ .hjm-color-swatches__item input:checked + .hjm-color-swatches__swatch { box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.15), 0 0 0 var(--hjm-color-swatch-gap) var(--hjm-color-bg), 0 0 0 calc(var(--hjm-color-swatch-gap) + var(--hjm-color-swatch-ring)) var(--hjm-color-text); }
3401
+ .hjm-color-swatches__item input:focus-visible + .hjm-color-swatches__swatch { outline: var(--hjm-focus-width, 2px) solid var(--hjm-color-focus); outline-offset: calc(var(--hjm-color-swatch-gap) + var(--hjm-color-swatch-ring) + 2px); }
3402
+ .hjm-color-swatches:disabled .hjm-color-swatches__item { cursor: not-allowed; opacity: 0.5; }
3363
3403
  /* SVG labels are decorative and print with the content; neither selection nor pointer input is intercepted. */
3364
3404
  .hjm-watermark { position: relative; isolation: isolate; }
3365
3405
  .hjm-watermark__content { position: relative; z-index: 0; overflow-wrap: anywhere; }
@@ -3664,8 +3704,8 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3664
3704
  (--hjm-comment-anchor-line, set per row), so like/more glyphs share the author line's centre instead of sitting
3665
3705
  12px below it. When HJM's own like/more is the last control (data-edge), the whole column takes the IconButton edge
3666
3706
  overhang: the 44-wide like count under the heart shares the column, so a margin on the button alone was absorbed. */
3667
- .hjm-comment-row__like { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start; margin-block-start: calc((var(--hjm-comment-anchor-line) - var(--hjm-control-button-medium)) / 2); }
3668
- .hjm-comment-row__like[data-edge="end"] { margin-inline-end: calc(-1 * var(--hjm-icon-button-edge-medium)); }
3707
+ .hjm-comment-row__like { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start; margin-block-start: calc((var(--hjm-comment-anchor-line) - var(--hjm-control-button-small)) / 2); }
3708
+ .hjm-comment-row__like[data-edge="end"] { margin-inline-end: calc(-1 * var(--hjm-icon-button-edge-small)); }
3669
3709
  .hjm-comment-row__like-count { text-align: center; }
3670
3710
  .hjm-comment-row__action { align-self: flex-start; padding: 0; border: 0; background: none; color: var(--hjm-color-text-muted); font: inherit; font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); font-weight: var(--hjm-text-emphasis-medium); cursor: pointer; }
3671
3711
  .hjm-comment-row__action:disabled { opacity: 0.5; cursor: default; }
@@ -3790,6 +3830,7 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3790
3830
 
3791
3831
  /* Full destination cards keep all names and widths stable; colors remain product semantic roles. */
3792
3832
  .hjm-bottom-navigation[data-selection="tile"] .hjm-bottom-navigation__surface { background: var(--hjm-color-surface-accent); }
3833
+ .hjm-bottom-navigation[data-selection="tile"][data-tone="neutral"] .hjm-bottom-navigation__surface { background: var(--hjm-color-surface); }
3793
3834
  .hjm-bottom-navigation[data-selection="tile"] .hjm-bottom-navigation__list { padding: var(--hjm-space-xxs); gap: var(--hjm-space-xxs); }
3794
3835
  .hjm-bottom-navigation[data-selection="tile"] .hjm-bottom-navigation__item[data-state="selected"] { background: var(--hjm-color-primary); color: var(--hjm-color-on-primary); }
3795
3836
  .hjm-bottom-navigation[data-selection="tile"] .hjm-bottom-navigation__item:not([data-state="selected"]):active { background: var(--hjm-bottom-navigation-pressed-background); }
@@ -3989,4 +4030,37 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3989
4030
  .hjm-chat-room__selected-name { max-inline-size:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
3990
4031
  :is(.hjm-chat-room__tool,.hjm-chat-room__photo,.hjm-chat-room__selected-item):focus-visible { outline:2px solid var(--hjm-color-content-brand); outline-offset:2px; }
3991
4032
 
4033
+ /* FollowListScreen already receives the screen body inset; external tab panels add no second gutter. */
4034
+ .hjm-follow-list__panel { padding-block: 0; }
4035
+
4036
+ /* Narrow pager placement without shrinking the vertical tap target or overlapping adjacent buttons. */
4037
+ .hjm-page-indicator[data-density="compact"][data-interactive="true"] { gap: 0; }
4038
+ .hjm-page-indicator[data-density="compact"] .hjm-page-indicator__dot { min-inline-size: var(--hjm-space-lg); inline-size: var(--hjm-space-lg); padding-inline: 0; }
4039
+
4040
+ /* Identity navigation preserves small avatar geometry while exposing a keyboard/touch target. */
4041
+ .hjm-identity-action { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; min-inline-size: var(--hjm-identity-target); min-block-size: var(--hjm-identity-target); margin: 0; padding: 0; border: 0; border-radius: var(--hjm-radius-full, 9999px); background: transparent; color: inherit; cursor: pointer; }
4042
+ .hjm-identity-action > span { display: inline-flex; }
4043
+ .hjm-identity-action:focus-visible { outline: 2px solid var(--hjm-color-content-brand); outline-offset: 2px; }
4044
+ .hjm-identity-action:active { opacity: var(--hjm-identity-pressed-opacity); }
4045
+ .hjm-identity-action:disabled { cursor: default; }
4046
+
4047
+ /* Independent identity navigation is a sibling of row commands, including links. */
4048
+ .hjm-list-row__profile { display: flex; flex: 0 0 auto; padding-inline-start: var(--hjm-list-row-inline); }
4049
+ .hjm-list-row-frame[data-leading-action] > .hjm-list-row { padding-inline-start: 0; }
4050
+ .hjm-list-row-frame[data-leading-action]:not([data-trailing-action]) > .hjm-list-row { padding-inline-end: var(--hjm-list-row-inline); }
4051
+
4052
+ .hjm-card[data-activation="overlay"] .hjm-card__leading[data-interactive] { position: relative; z-index: 1; }
4053
+
4054
+ /* Header dismissal keeps a single modal surface and leaves the action viewport scrollable. */
4055
+ .hjm-menu__content[data-presentation="bottom"][data-dismiss-placement="header"] { background: var(--hjm-color-bg); padding: var(--hjm-space-sm); }
4056
+ .hjm-menu__header { display: flex; align-items: center; gap: var(--hjm-space-sm); flex-shrink: 0; }
4057
+ .hjm-menu__heading { flex: 1; min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
4058
+ .hjm-menu__title { font-weight: var(--hjm-text-emphasis-strong); }
4059
+ .hjm-menu__subtitle { font-size: var(--hjm-type-label-size); color: var(--hjm-color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
4060
+
4061
+ /* Relationship lists use the large Avatar (48) and 64px rows so identity stays legible beside actions. */
4062
+ .hjm-follow-list__person { min-block-size: 64px; }
4063
+ .hjm-list-row__leading[data-size="large"] { inline-size: 48px; block-size: 48px; }
4064
+ .hjm-follow-list__relationship { min-inline-size: 108px; }
4065
+
3992
4066
  }
@@ -62,7 +62,7 @@ export function LineScore({ teams, totals, currentPeriod = null, minPeriods, ren
62
62
  return;
63
63
  container.querySelector(`thead [data-period="${focusPeriod}"]`)?.scrollIntoView({ block: "nearest", inline: "nearest" });
64
64
  }, [focusPeriod, periods.length]);
65
- return (_jsx("div", { ref: host, className: classNames("hjm-table-family", "hjm-line-score", className), style: { ...withFamilyStyle(layoutStyle), "--hjm-line-score-total-count": totalColumns.length }, children: _jsxs("table", { className: "hjm-line-score__table", "aria-label": accessibilityLabel, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("td", { className: "hjm-line-score__team" }), periods.map((column, index) => {
65
+ return (_jsx("div", { ref: host, className: classNames("hjm-table-family", "hjm-line-score", className), style: { ...withFamilyStyle(layoutStyle), "--hjm-line-score-current-background": tableCssColor(dataTableFamilyRecipe.currentPeriod.background), "--hjm-line-score-current-color": tableCssColor(dataTableFamilyRecipe.currentPeriod.color), "--hjm-line-score-total-count": totalColumns.length }, children: _jsxs("table", { className: "hjm-line-score__table", "aria-label": accessibilityLabel, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("td", { className: "hjm-line-score__team" }), periods.map((column, index) => {
66
66
  const live = score.currentPeriod === index + 1;
67
67
  return _jsx("th", { scope: "col", className: "hjm-line-score__period", "data-period": index + 1, "aria-current": live ? "true" : undefined, "data-current": live || undefined, children: column.header }, column.id);
68
68
  }), totalColumns.map((column, index) => (_jsx("th", { scope: "col", className: classNames("hjm-line-score__total", index === 0 && "hjm-line-score__total-edge"), style: totalOffset(totalColumns.length, index), children: column.header }, column.id)))] }) }), _jsx("tbody", { children: teams.map((team) => (_jsxs("tr", { "data-leader": score.leaderId === team.id || undefined, children: [_jsx("th", { scope: "row", className: "hjm-line-score__team", children: _jsxs("span", { className: "hjm-line-score__team-content", children: [renderTeam?.(team), _jsx("span", { children: team.name })] }) }), periods.map((column, index) => {
@@ -1 +1 @@
1
- {"version":3,"file":"table-family.js","sourceRoot":"","sources":["../src/table-family.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { useLayoutEffect, useRef, type CSSProperties, type ReactNode } from \"react\";\nimport type { ColorReference } from \"@hjmds/design-contracts/color-references\";\nimport {\n dataTableFamilyRecipe, formatLineScoreCell, resolveComparisonRow, resolveLineScore, resolveMatrix,\n type ComparisonRow, type DataTableCellHeat, type DataTableCellTone, type LineScoreTeam, type MatrixCell,\n} from \"@hjmds/design-contracts/components/data-table\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\n/*\n * Table family companions (2026-10-14): layouts products kept hand-building next to DataTable.\n * LineScore follows MLB/ESPN game headers, MatrixTable a head-to-head cross table, ComparisonTable\n * the ESPN matchup rows. Geometry and rules live in the data-table contract; these only draw.\n */\n\nfunction kebab(value: string): string {\n return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n}\n\n/** Recipe colors resolve through the provider's CSS variables so a theme switch repaints without re-rendering (same as Chart). */\nexport function tableCssColor(reference: ColorReference): string {\n const name = reference.source === \"theme\"\n ? `--hjm-color-${kebab(reference.key)}`\n : reference.source === \"accent\" ? `--hjm-accent-${kebab(reference.key)}` : `--hjm-accent-fill-${kebab(reference.key)}`;\n return reference.alpha === undefined || reference.alpha === 1\n ? `var(${name})`\n : `color-mix(in srgb, var(${name}) ${Math.round(reference.alpha * 100)}%, transparent)`;\n}\n\n/** Live period and \"my team\" row share the family highlight tint. */\nconst familyStyle = { \"--hjm-table-family-selected\": tableCssColor(dataTableFamilyRecipe.highlight.background) } as CSSProperties;\nconst withFamilyStyle = (layoutStyle: HjmCompositionStyleProp | undefined) => ({ ...familyStyle, ...layoutStyle }) as CSSProperties;\n\nexport type TableHeatColors = Readonly<{ high: string; low: string }>;\n\n/**\n * Cell emphasis as inline style. Heat paints a background *image* so pinned cells keep their opaque\n * canvas color underneath and scrolled content never shows through the translucent tint.\n */\nexport function tableCellEmphasis(\n decoration: Readonly<{ tone?: DataTableCellTone | null; heat?: DataTableCellHeat | null }> | null | undefined,\n heatColors?: TableHeatColors,\n): Readonly<{ style: CSSProperties; tone?: DataTableCellTone; heat?: string }> {\n if (!decoration) return { style: {} };\n const style: Record<string, string | number> = {};\n const tone = decoration.tone ?? undefined, heat = decoration.heat ?? null;\n if (tone) {\n style.color = tableCssColor(dataTableFamilyRecipe.tone[tone].color);\n style.fontWeight = dataTableFamilyRecipe.tone[tone].fontWeight;\n }\n if (heat) {\n const base = heatColors?.[heat.side] ?? tableCssColor(dataTableFamilyRecipe.heat[heat.side]);\n style[\"--hjm-data-table-heat\"] = `color-mix(in srgb, ${base} ${Math.round(dataTableFamilyRecipe.heatAlpha[heat.strength] * 100)}%, transparent)`;\n }\n return { style: style as CSSProperties, ...(tone ? { tone } : {}), ...(heat ? { heat: `${heat.side}-${heat.strength}` } : {}) };\n}\n\n/* ---------------------------------------------- Line score ------------------------------------- */\n\n/**\n * Team and total columns stay pinned while only the periods scroll, as on Native: at 402px the totals — the result —\n * scrolled off with the extra innings (2026-10-17 review E17). Totals have a fixed width so each can pin at its offset.\n */\nconst totalOffset = (count: number, index: number): CSSProperties => ({ insetInlineEnd: `calc(var(--hjm-line-score-total-width) * ${count - 1 - index})` });\n\nexport type LineScoreProps = Readonly<{\n teams: readonly LineScoreTeam[];\n /** Total column headers in order, e.g. [\"R\", \"H\", \"E\", \"B\"]. The first one decides the leader. */\n totals: readonly string[];\n /** Live period (1-based) to highlight. */\n currentPeriod?: number | null;\n minPeriods?: number;\n /** Optional leading content per team (logo/badge). */\n renderTeam?: (team: LineScoreTeam) => ReactNode;\n /** Accessible name of the table (prop name kept for Native parity). */\n accessibilityLabel: string;\n className?: string;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport function LineScore({ teams, totals, currentPeriod = null, minPeriods, renderTeam, accessibilityLabel, className, layoutStyle }: LineScoreProps) {\n const score = resolveLineScore(teams, { totals, currentPeriod, ...(minPeriods !== undefined ? { minPeriods } : {}) });\n const periods = score.columns.filter((column) => column.kind === \"period\");\n const totalColumns = score.columns.filter((column) => column.kind === \"total\");\n // Open the period strip at the live (or latest) period, as Native: starting at inning 1 hid extra innings behind the\n // pinned totals and read as a shorter game (2026-10-17 review N4). scroll-padding keeps it clear of the totals.\n const host = useRef<HTMLDivElement>(null);\n const focusPeriod = score.currentPeriod ?? periods.length;\n useLayoutEffect(() => {\n const container = host.current;\n if (!container || container.scrollWidth <= container.clientWidth) return;\n container.querySelector<HTMLElement>(`thead [data-period=\"${focusPeriod}\"]`)?.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n }, [focusPeriod, periods.length]);\n return (\n <div ref={host} className={classNames(\"hjm-table-family\", \"hjm-line-score\", className)} style={{ ...withFamilyStyle(layoutStyle), \"--hjm-line-score-total-count\": totalColumns.length } as CSSProperties}>\n <table className=\"hjm-line-score__table\" aria-label={accessibilityLabel}>\n <thead>\n <tr>\n <td className=\"hjm-line-score__team\" />\n {periods.map((column, index) => {\n const live = score.currentPeriod === index + 1;\n return <th key={column.id} scope=\"col\" className=\"hjm-line-score__period\" data-period={index + 1} aria-current={live ? \"true\" : undefined} data-current={live || undefined}>{column.header}</th>;\n })}\n {totalColumns.map((column, index) => (\n <th key={column.id} scope=\"col\" className={classNames(\"hjm-line-score__total\", index === 0 && \"hjm-line-score__total-edge\")} style={totalOffset(totalColumns.length, index)}>{column.header}</th>\n ))}\n </tr>\n </thead>\n <tbody>\n {teams.map((team) => (\n <tr key={team.id} data-leader={score.leaderId === team.id || undefined}>\n <th scope=\"row\" className=\"hjm-line-score__team\">\n <span className=\"hjm-line-score__team-content\">{renderTeam?.(team)}<span>{team.name}</span></span>\n </th>\n {periods.map((column, index) => {\n const value = team.periods[index];\n return <td key={column.id} className=\"hjm-line-score__period\" data-current={score.currentPeriod === index + 1 || undefined} data-scored={typeof value === \"number\" && value > 0 || undefined}>{formatLineScoreCell(value)}</td>;\n })}\n {totalColumns.map((column, index) => (\n <td key={column.id} className={classNames(\"hjm-line-score__total\", index === 0 && \"hjm-line-score__total-edge\")} style={totalOffset(totalColumns.length, index)}>{team.totals[column.header] ?? \"—\"}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/* ---------------------------------------------- Matrix table ----------------------------------- */\n\nexport type MatrixTableProps<Key extends string = string> = Readonly<{\n ids: readonly Key[];\n /** Short header per id (team short name). */\n labelOf: (id: Key) => string;\n getCell: (row: Key, column: Key) => MatrixCell | null;\n /** Row id to highlight (my team). */\n highlightId?: Key | null;\n heatColors?: TableHeatColors;\n accessibilityLabel: string;\n className?: string;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport function MatrixTable<Key extends string = string>({ ids, labelOf, getCell, highlightId = null, heatColors, accessibilityLabel, className, layoutStyle }: MatrixTableProps<Key>) {\n const matrix = resolveMatrix(ids, getCell);\n return (\n <div className={classNames(\"hjm-table-family\", \"hjm-matrix-table\", className)} style={withFamilyStyle(layoutStyle)}>\n <table className=\"hjm-matrix-table__table\" aria-label={accessibilityLabel}>\n <thead>\n <tr>\n <td className=\"hjm-matrix-table__corner\" />\n {ids.map((id) => <th key={id} scope=\"col\">{labelOf(id)}</th>)}\n </tr>\n </thead>\n <tbody>\n {matrix.map((cells, rowIndex) => {\n const rowId = ids[rowIndex]!;\n return (\n <tr key={rowId} data-highlighted={rowId === highlightId || undefined}>\n <th scope=\"row\">{labelOf(rowId)}</th>\n {cells.map((cell, columnIndex) => {\n // The diagonal is a team against itself: blank and hidden, not \"no record\".\n if (cell === \"self\") return <td key={ids[columnIndex]} className=\"hjm-matrix-table__self\" aria-hidden=\"true\" />;\n const emphasis = tableCellEmphasis(cell, heatColors);\n return <td key={ids[columnIndex]} className={emphasis.heat ? \"hjm-table-family__heat\" : undefined} style={emphasis.style} data-tone={emphasis.tone} data-heat={emphasis.heat}>{cell?.label ?? \"—\"}</td>;\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n/* ---------------------------------------------- Comparison table ------------------------------- */\n\nexport type ComparisonTableProps = Readonly<{\n rows: readonly ComparisonRow[];\n /** Side names and accent colors (team colors). */\n sides: readonly [Readonly<{ name: string; color: string }>, Readonly<{ name: string; color: string }>];\n /** Hide duplicate visual names when the two sides are already identified above; spoken row labels retain them. */\n showSideNames?: boolean;\n accessibilityLabel: string;\n className?: string;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport function ComparisonTable({ rows, sides, showSideNames = true, accessibilityLabel, className, layoutStyle }: ComparisonTableProps) {\n return (\n <section className={classNames(\"hjm-table-family\", \"hjm-comparison-table\", className)} style={withFamilyStyle(layoutStyle)} aria-label={accessibilityLabel}>\n {showSideNames && <div className=\"hjm-comparison-table__sides\" aria-hidden=\"true\">\n {sides.map((side, index) => <span key={index} style={{ color: side.color }}>{side.name}</span>)}\n </div>}\n <ul className=\"hjm-comparison-table__rows\" role=\"list\">\n {rows.map((row) => {\n const { winner, shares } = resolveComparisonRow(row);\n const shown = row.display ?? [row.values[0] === null ? \"—\" : String(row.values[0]), row.values[1] === null ? \"—\" : String(row.values[1])];\n return (\n <li key={row.id} className=\"hjm-comparison-table__row\" data-winner={winner ?? undefined}>\n {/* One sentence for assistive tech; the visual grid and bars are decoration. */}\n <span className=\"hjm-visually-hidden\">{`${row.label} ${sides[0].name} ${shown[0]}, ${sides[1].name} ${shown[1]}`}</span>\n <div className=\"hjm-comparison-table__values\" aria-hidden=\"true\">\n <span data-win={winner === 0 || undefined}>{shown[0]}</span>\n <span className=\"hjm-comparison-table__label\">{row.label}</span>\n <span data-win={winner === 1 || undefined}>{shown[1]}</span>\n </div>\n <div className=\"hjm-comparison-table__bars\" aria-hidden=\"true\">\n {([0, 1] as const).map((index) => (\n <span key={index} className=\"hjm-comparison-table__track\" data-side={index}>\n <span\n className=\"hjm-comparison-table__bar\"\n style={{ inlineSize: `${Math.round(shares[index] * 1000) / 10}%`, background: sides[index].color, opacity: winner === null || winner === index ? 1 : 0.6 }}\n />\n </span>\n ))}\n </div>\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n"]}
1
+ {"version":3,"file":"table-family.js","sourceRoot":"","sources":["../src/table-family.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { useLayoutEffect, useRef, type CSSProperties, type ReactNode } from \"react\";\nimport type { ColorReference } from \"@hjmds/design-contracts/color-references\";\nimport {\n dataTableFamilyRecipe, formatLineScoreCell, resolveComparisonRow, resolveLineScore, resolveMatrix,\n type ComparisonRow, type DataTableCellHeat, type DataTableCellTone, type LineScoreTeam, type MatrixCell,\n} from \"@hjmds/design-contracts/components/data-table\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\n/*\n * Table family companions (2026-10-14): layouts products kept hand-building next to DataTable.\n * LineScore follows MLB/ESPN game headers, MatrixTable a head-to-head cross table, ComparisonTable\n * the ESPN matchup rows. Geometry and rules live in the data-table contract; these only draw.\n */\n\nfunction kebab(value: string): string {\n return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n}\n\n/** Recipe colors resolve through the provider's CSS variables so a theme switch repaints without re-rendering (same as Chart). */\nexport function tableCssColor(reference: ColorReference): string {\n const name = reference.source === \"theme\"\n ? `--hjm-color-${kebab(reference.key)}`\n : reference.source === \"accent\" ? `--hjm-accent-${kebab(reference.key)}` : `--hjm-accent-fill-${kebab(reference.key)}`;\n return reference.alpha === undefined || reference.alpha === 1\n ? `var(${name})`\n : `color-mix(in srgb, var(${name}) ${Math.round(reference.alpha * 100)}%, transparent)`;\n}\n\n/** Live period and \"my team\" row share the family highlight tint. */\nconst familyStyle = { \"--hjm-table-family-selected\": tableCssColor(dataTableFamilyRecipe.highlight.background) } as CSSProperties;\nconst withFamilyStyle = (layoutStyle: HjmCompositionStyleProp | undefined) => ({ ...familyStyle, ...layoutStyle }) as CSSProperties;\n\nexport type TableHeatColors = Readonly<{ high: string; low: string }>;\n\n/**\n * Cell emphasis as inline style. Heat paints a background *image* so pinned cells keep their opaque\n * canvas color underneath and scrolled content never shows through the translucent tint.\n */\nexport function tableCellEmphasis(\n decoration: Readonly<{ tone?: DataTableCellTone | null; heat?: DataTableCellHeat | null }> | null | undefined,\n heatColors?: TableHeatColors,\n): Readonly<{ style: CSSProperties; tone?: DataTableCellTone; heat?: string }> {\n if (!decoration) return { style: {} };\n const style: Record<string, string | number> = {};\n const tone = decoration.tone ?? undefined, heat = decoration.heat ?? null;\n if (tone) {\n style.color = tableCssColor(dataTableFamilyRecipe.tone[tone].color);\n style.fontWeight = dataTableFamilyRecipe.tone[tone].fontWeight;\n }\n if (heat) {\n const base = heatColors?.[heat.side] ?? tableCssColor(dataTableFamilyRecipe.heat[heat.side]);\n style[\"--hjm-data-table-heat\"] = `color-mix(in srgb, ${base} ${Math.round(dataTableFamilyRecipe.heatAlpha[heat.strength] * 100)}%, transparent)`;\n }\n return { style: style as CSSProperties, ...(tone ? { tone } : {}), ...(heat ? { heat: `${heat.side}-${heat.strength}` } : {}) };\n}\n\n/* ---------------------------------------------- Line score ------------------------------------- */\n\n/**\n * Team and total columns stay pinned while only the periods scroll, as on Native: at 402px the totals — the result —\n * scrolled off with the extra innings (2026-10-17 review E17). Totals have a fixed width so each can pin at its offset.\n */\nconst totalOffset = (count: number, index: number): CSSProperties => ({ insetInlineEnd: `calc(var(--hjm-line-score-total-width) * ${count - 1 - index})` });\n\nexport type LineScoreProps = Readonly<{\n teams: readonly LineScoreTeam[];\n /** Total column headers in order, e.g. [\"R\", \"H\", \"E\", \"B\"]. The first one decides the leader. */\n totals: readonly string[];\n /** Live period (1-based) to highlight. */\n currentPeriod?: number | null;\n minPeriods?: number;\n /** Optional leading content per team (logo/badge). */\n renderTeam?: (team: LineScoreTeam) => ReactNode;\n /** Accessible name of the table (prop name kept for Native parity). */\n accessibilityLabel: string;\n className?: string;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport function LineScore({ teams, totals, currentPeriod = null, minPeriods, renderTeam, accessibilityLabel, className, layoutStyle }: LineScoreProps) {\n const score = resolveLineScore(teams, { totals, currentPeriod, ...(minPeriods !== undefined ? { minPeriods } : {}) });\n const periods = score.columns.filter((column) => column.kind === \"period\");\n const totalColumns = score.columns.filter((column) => column.kind === \"total\");\n // Open the period strip at the live (or latest) period, as Native: starting at inning 1 hid extra innings behind the\n // pinned totals and read as a shorter game (2026-10-17 review N4). scroll-padding keeps it clear of the totals.\n const host = useRef<HTMLDivElement>(null);\n const focusPeriod = score.currentPeriod ?? periods.length;\n useLayoutEffect(() => {\n const container = host.current;\n if (!container || container.scrollWidth <= container.clientWidth) return;\n container.querySelector<HTMLElement>(`thead [data-period=\"${focusPeriod}\"]`)?.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n }, [focusPeriod, periods.length]);\n return (\n <div ref={host} className={classNames(\"hjm-table-family\", \"hjm-line-score\", className)} style={{ ...withFamilyStyle(layoutStyle), \"--hjm-line-score-current-background\": tableCssColor(dataTableFamilyRecipe.currentPeriod.background), \"--hjm-line-score-current-color\": tableCssColor(dataTableFamilyRecipe.currentPeriod.color), \"--hjm-line-score-total-count\": totalColumns.length } as CSSProperties}>\n <table className=\"hjm-line-score__table\" aria-label={accessibilityLabel}>\n <thead>\n <tr>\n <td className=\"hjm-line-score__team\" />\n {periods.map((column, index) => {\n const live = score.currentPeriod === index + 1;\n return <th key={column.id} scope=\"col\" className=\"hjm-line-score__period\" data-period={index + 1} aria-current={live ? \"true\" : undefined} data-current={live || undefined}>{column.header}</th>;\n })}\n {totalColumns.map((column, index) => (\n <th key={column.id} scope=\"col\" className={classNames(\"hjm-line-score__total\", index === 0 && \"hjm-line-score__total-edge\")} style={totalOffset(totalColumns.length, index)}>{column.header}</th>\n ))}\n </tr>\n </thead>\n <tbody>\n {teams.map((team) => (\n <tr key={team.id} data-leader={score.leaderId === team.id || undefined}>\n <th scope=\"row\" className=\"hjm-line-score__team\">\n <span className=\"hjm-line-score__team-content\">{renderTeam?.(team)}<span>{team.name}</span></span>\n </th>\n {periods.map((column, index) => {\n const value = team.periods[index];\n return <td key={column.id} className=\"hjm-line-score__period\" data-current={score.currentPeriod === index + 1 || undefined} data-scored={typeof value === \"number\" && value > 0 || undefined}>{formatLineScoreCell(value)}</td>;\n })}\n {totalColumns.map((column, index) => (\n <td key={column.id} className={classNames(\"hjm-line-score__total\", index === 0 && \"hjm-line-score__total-edge\")} style={totalOffset(totalColumns.length, index)}>{team.totals[column.header] ?? \"—\"}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/* ---------------------------------------------- Matrix table ----------------------------------- */\n\nexport type MatrixTableProps<Key extends string = string> = Readonly<{\n ids: readonly Key[];\n /** Short header per id (team short name). */\n labelOf: (id: Key) => string;\n getCell: (row: Key, column: Key) => MatrixCell | null;\n /** Row id to highlight (my team). */\n highlightId?: Key | null;\n heatColors?: TableHeatColors;\n accessibilityLabel: string;\n className?: string;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport function MatrixTable<Key extends string = string>({ ids, labelOf, getCell, highlightId = null, heatColors, accessibilityLabel, className, layoutStyle }: MatrixTableProps<Key>) {\n const matrix = resolveMatrix(ids, getCell);\n return (\n <div className={classNames(\"hjm-table-family\", \"hjm-matrix-table\", className)} style={withFamilyStyle(layoutStyle)}>\n <table className=\"hjm-matrix-table__table\" aria-label={accessibilityLabel}>\n <thead>\n <tr>\n <td className=\"hjm-matrix-table__corner\" />\n {ids.map((id) => <th key={id} scope=\"col\">{labelOf(id)}</th>)}\n </tr>\n </thead>\n <tbody>\n {matrix.map((cells, rowIndex) => {\n const rowId = ids[rowIndex]!;\n return (\n <tr key={rowId} data-highlighted={rowId === highlightId || undefined}>\n <th scope=\"row\">{labelOf(rowId)}</th>\n {cells.map((cell, columnIndex) => {\n // The diagonal is a team against itself: blank and hidden, not \"no record\".\n if (cell === \"self\") return <td key={ids[columnIndex]} className=\"hjm-matrix-table__self\" aria-hidden=\"true\" />;\n const emphasis = tableCellEmphasis(cell, heatColors);\n return <td key={ids[columnIndex]} className={emphasis.heat ? \"hjm-table-family__heat\" : undefined} style={emphasis.style} data-tone={emphasis.tone} data-heat={emphasis.heat}>{cell?.label ?? \"—\"}</td>;\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n/* ---------------------------------------------- Comparison table ------------------------------- */\n\nexport type ComparisonTableProps = Readonly<{\n rows: readonly ComparisonRow[];\n /** Side names and accent colors (team colors). */\n sides: readonly [Readonly<{ name: string; color: string }>, Readonly<{ name: string; color: string }>];\n /** Hide duplicate visual names when the two sides are already identified above; spoken row labels retain them. */\n showSideNames?: boolean;\n accessibilityLabel: string;\n className?: string;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport function ComparisonTable({ rows, sides, showSideNames = true, accessibilityLabel, className, layoutStyle }: ComparisonTableProps) {\n return (\n <section className={classNames(\"hjm-table-family\", \"hjm-comparison-table\", className)} style={withFamilyStyle(layoutStyle)} aria-label={accessibilityLabel}>\n {showSideNames && <div className=\"hjm-comparison-table__sides\" aria-hidden=\"true\">\n {sides.map((side, index) => <span key={index} style={{ color: side.color }}>{side.name}</span>)}\n </div>}\n <ul className=\"hjm-comparison-table__rows\" role=\"list\">\n {rows.map((row) => {\n const { winner, shares } = resolveComparisonRow(row);\n const shown = row.display ?? [row.values[0] === null ? \"—\" : String(row.values[0]), row.values[1] === null ? \"—\" : String(row.values[1])];\n return (\n <li key={row.id} className=\"hjm-comparison-table__row\" data-winner={winner ?? undefined}>\n {/* One sentence for assistive tech; the visual grid and bars are decoration. */}\n <span className=\"hjm-visually-hidden\">{`${row.label} ${sides[0].name} ${shown[0]}, ${sides[1].name} ${shown[1]}`}</span>\n <div className=\"hjm-comparison-table__values\" aria-hidden=\"true\">\n <span data-win={winner === 0 || undefined}>{shown[0]}</span>\n <span className=\"hjm-comparison-table__label\">{row.label}</span>\n <span data-win={winner === 1 || undefined}>{shown[1]}</span>\n </div>\n <div className=\"hjm-comparison-table__bars\" aria-hidden=\"true\">\n {([0, 1] as const).map((index) => (\n <span key={index} className=\"hjm-comparison-table__track\" data-side={index}>\n <span\n className=\"hjm-comparison-table__bar\"\n style={{ inlineSize: `${Math.round(shares[index] * 1000) / 10}%`, background: sides[index].color, opacity: winner === null || winner === index ? 1 : 0.6 }}\n />\n </span>\n ))}\n </div>\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n"]}
package/dist/toast.d.ts CHANGED
@@ -6,7 +6,7 @@ export type ToastProps = Omit<HTMLAttributes<HTMLDivElement>, "children" | "titl
6
6
  onDismissRequest: (reason: ToastDismissReason) => void;
7
7
  }>;
8
8
  /** Controlled single-toast renderer; ToastProvider supplies the full FIFO lifecycle. */
9
- export declare const Toast: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "title" | "children"> & Readonly<{
9
+ export declare const Toast: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children" | "title"> & Readonly<{
10
10
  descriptor: ToastDescriptor;
11
11
  onDismissRequest: (reason: ToastDismissReason) => void;
12
12
  }> & import("react").RefAttributes<HTMLDivElement>>;
package/dist/top-bar.d.ts CHANGED
@@ -24,7 +24,7 @@ export type TopBarProps = Omit<HTMLAttributes<HTMLDivElement>, "title" | "childr
24
24
  layoutStyle?: HjmCompositionStyleProp;
25
25
  }>;
26
26
  /** Screen chrome stays composable inside pages and dialogs, without adding a second banner landmark. */
27
- export declare const TopBar: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "title" | "children"> & Readonly<{
27
+ export declare const TopBar: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children" | "title"> & Readonly<{
28
28
  title?: string;
29
29
  /** Product control in the shared title slot; exclusive with text title affordances. */
30
30
  titleContent?: ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hjmds/react",
3
- "version": "1.46.1",
3
+ "version": "1.48.0",
4
4
  "description": "Accessible React 19 renderers for HJM design contracts.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -604,6 +604,11 @@
604
604
  "import": "./dist/shortcut-rail.js",
605
605
  "default": "./dist/shortcut-rail.js"
606
606
  },
607
+ "./share-sheet": {
608
+ "types": "./dist/share-sheet.d.ts",
609
+ "import": "./dist/share-sheet.js",
610
+ "default": "./dist/share-sheet.js"
611
+ },
607
612
  "./time-picker": {
608
613
  "types": "./dist/time-picker.d.ts",
609
614
  "import": "./dist/time-picker.js",
@@ -613,6 +618,11 @@
613
618
  "types": "./dist/image-viewer.d.ts",
614
619
  "import": "./dist/image-viewer.js",
615
620
  "default": "./dist/image-viewer.js"
621
+ },
622
+ "./follow-list": {
623
+ "types": "./dist/follow-list.d.ts",
624
+ "import": "./dist/follow-list.js",
625
+ "default": "./dist/follow-list.js"
616
626
  }
617
627
  },
618
628
  "files": [
@@ -623,7 +633,7 @@
623
633
  "THIRD_PARTY_NOTICES.md"
624
634
  ],
625
635
  "peerDependencies": {
626
- "@hjmds/design-contracts": ">=1.46.0 <1.47.0",
636
+ "@hjmds/design-contracts": ">=1.48.0 <1.49.0",
627
637
  "react": ">=19.0.0",
628
638
  "react-dom": ">=19.0.0",
629
639
  "@number-flow/react": "0.6.2",
@@ -661,7 +671,7 @@
661
671
  "@blobatar/react": "2.7.0",
662
672
  "lucide-react": "1.59.0",
663
673
  "vite": "8.3.4",
664
- "@hjmds/design-contracts": "1.46.1"
674
+ "@hjmds/design-contracts": "1.48.0"
665
675
  },
666
676
  "peerDependenciesMeta": {
667
677
  "@number-flow/react": {