@hjmds/react 1.35.1 → 1.36.1
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/dist/evidence.d.ts +1 -1
- package/dist/evidence.js +1 -1
- package/dist/evidence.js.map +1 -1
- package/dist/forms.js +1 -1
- package/dist/forms.js.map +1 -1
- package/dist/internal/photo-source-icon.d.ts +5 -0
- package/dist/internal/photo-source-icon.d.ts.map +1 -0
- package/dist/internal/photo-source-icon.js +13 -0
- package/dist/internal/photo-source-icon.js.map +1 -0
- package/dist/overlays.d.ts +5 -2
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +35 -29
- package/dist/overlays.js.map +1 -1
- package/dist/screen-flows.d.ts +4 -0
- package/dist/screen-flows.d.ts.map +1 -1
- package/dist/screen-flows.js +5 -3
- package/dist/screen-flows.js.map +1 -1
- package/dist/styles.css +34 -8
- package/dist/styles.layered.css +34 -8
- package/dist/supplemental-navigation.d.ts +4 -0
- package/dist/supplemental-navigation.d.ts.map +1 -1
- package/dist/supplemental-navigation.js +7 -5
- package/dist/supplemental-navigation.js.map +1 -1
- package/dist/task-controls.js +1 -1
- package/dist/task-controls.js.map +1 -1
- package/package.json +3 -3
package/dist/styles.css
CHANGED
|
@@ -1061,6 +1061,9 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
1061
1061
|
the avatar box in product styles. */
|
|
1062
1062
|
.hjm-list-row__leading { display: flex; align-items: center; justify-content: center; inline-size: var(--hjm-list-row-leading-size); block-size: var(--hjm-list-row-leading-size); overflow: hidden; }
|
|
1063
1063
|
.hjm-list-row__leading[data-shape="circle"] { border-radius: var(--hjm-radius-full); }
|
|
1064
|
+
/* Photo source peers share ListRow geometry; only their decorative brand plate is specialized. */
|
|
1065
|
+
.hjm-photo-source__icon { display: grid; place-items: center; inline-size: 100%; block-size: 100%; border-radius: var(--hjm-radius-md); }
|
|
1066
|
+
.hjm-photo-source__icon svg { inline-size: 24px; block-size: 24px; }
|
|
1064
1067
|
.hjm-list-row__content { flex: 1 1 auto; min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
|
|
1065
1068
|
/* listRowRecipe title bodyLarge / description body (2026-10-17: Web inherited 14 for both while Native used the recipe). */
|
|
1066
1069
|
.hjm-list-row__title { 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; }
|
|
@@ -2383,7 +2386,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2383
2386
|
display: flex;
|
|
2384
2387
|
flex-wrap: wrap;
|
|
2385
2388
|
justify-content: flex-end;
|
|
2386
|
-
|
|
2389
|
+
/* Match actionGroupRecipe: 8px in either direction (2026-10-20 user request). */
|
|
2390
|
+
gap: var(--hjm-space-xs);
|
|
2387
2391
|
padding: 0 var(--hjm-space-lg) var(--hjm-space-lg);
|
|
2388
2392
|
}
|
|
2389
2393
|
.hjm-dialog__close {
|
|
@@ -2675,6 +2679,27 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2675
2679
|
.hjm-menu__leading,
|
|
2676
2680
|
.hjm-menu__trailing { flex: 0 0 auto; color: var(--hjm-color-text-muted); }
|
|
2677
2681
|
|
|
2682
|
+
/* Three Menu presentations share items and focus semantics; modal chrome never belongs to a consumer. */
|
|
2683
|
+
.hjm-menu-positioner[data-presentation="bottom"] { align-items: end; padding-block-end: max(var(--hjm-space-md), env(safe-area-inset-bottom)); }
|
|
2684
|
+
.hjm-menu__content[data-presentation="grouped"],
|
|
2685
|
+
.hjm-menu__content[data-presentation="bottom"] {
|
|
2686
|
+
position: relative; inset: auto; display: flex; flex-direction: column; gap: var(--hjm-space-xs);
|
|
2687
|
+
inline-size: min(18rem, 100%); min-inline-size: 0; max-inline-size: 100%;
|
|
2688
|
+
max-block-size: calc(100dvh - 2 * var(--hjm-space-md)); padding: var(--hjm-space-sm);
|
|
2689
|
+
border-radius: var(--hjm-radius-lg);
|
|
2690
|
+
}
|
|
2691
|
+
.hjm-menu__content[data-presentation="bottom"] { inline-size: min(26.25rem, 100%); padding: 0; border: 0; background: transparent; box-shadow: none; }
|
|
2692
|
+
.hjm-menu__content[data-presentation="bottom"] .hjm-menu__viewport { background: var(--hjm-color-bg); }
|
|
2693
|
+
.hjm-menu__content[data-presentation="grouped"] .hjm-menu__viewport,
|
|
2694
|
+
.hjm-menu__content[data-presentation="bottom"] .hjm-menu__viewport { min-block-size: 0; overflow: auto; border-radius: var(--hjm-radius-md); }
|
|
2695
|
+
.hjm-menu__content[data-presentation="grouped"] .hjm-menu__viewport { background: var(--hjm-color-surface); }
|
|
2696
|
+
.hjm-menu__content[data-presentation="anchored"] .hjm-menu__item + .hjm-menu__item,
|
|
2697
|
+
.hjm-menu__content[data-presentation="grouped"] .hjm-menu__item + .hjm-menu__item,
|
|
2698
|
+
.hjm-menu__content[data-presentation="bottom"] .hjm-menu__item + .hjm-menu__item { border-block-start: 1px solid var(--hjm-color-border); border-radius: 0; }
|
|
2699
|
+
.hjm-menu__content[data-presentation="grouped"][data-density="comfortable"] .hjm-menu__item { min-block-size: 3.25rem; }
|
|
2700
|
+
.hjm-menu__content[data-presentation="grouped"] > .hjm-button,
|
|
2701
|
+
.hjm-menu__content[data-presentation="bottom"] > .hjm-button { flex-shrink: 0; inline-size: 100%; }
|
|
2702
|
+
|
|
2678
2703
|
/* Advanced forms --------------------------------------------------------- */
|
|
2679
2704
|
.hjm-select__native { appearance: none; padding-inline-end: calc(var(--hjm-space-lg) + var(--hjm-space-sm)); cursor: pointer; }
|
|
2680
2705
|
.hjm-select__anchor { position: relative; min-inline-size: 0; }
|
|
@@ -3397,13 +3422,13 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3397
3422
|
.hjm-chat-message[data-direction="outgoing"] .hjm-chat-message__body { flex-direction: row-reverse; }
|
|
3398
3423
|
.hjm-chat-message__bubble { border-radius: 14px; background: var(--hjm-color-surface); padding: 6px 10px; min-inline-size: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
|
|
3399
3424
|
.hjm-chat-message[data-direction="outgoing"] .hjm-chat-message__bubble { background: var(--hjm-color-surface-accent); }
|
|
3400
|
-
/*
|
|
3425
|
+
/* Tighten the first corner to join the overlapping rounded tip. */
|
|
3401
3426
|
.hjm-chat-message[data-tail] .hjm-chat-message__bubble { position: relative; border-start-start-radius: 4px; }
|
|
3402
|
-
|
|
3427
|
+
/* The reference tip follows the top edge; its curved underside joins the bubble (2026-10-20). */
|
|
3428
|
+
.hjm-chat-message[data-tail] .hjm-chat-message__bubble::before { content: ""; position: absolute; top: 0; inset-inline-start: -6px; width: 11px; height: 10px; border-start-start-radius: 1px; border-end-start-radius: 10px; background: var(--hjm-color-surface); pointer-events: none; }
|
|
3403
3429
|
.hjm-chat-message[data-tail][data-direction="outgoing"] .hjm-chat-message__bubble { border-start-start-radius: 14px; border-start-end-radius: 4px; }
|
|
3404
|
-
.hjm-chat-message[data-tail][data-direction="outgoing"] .hjm-chat-message__bubble::before { inset-inline-start: auto; inset-inline-end: -6px;
|
|
3405
|
-
/*
|
|
3406
|
-
[dir="rtl"] .hjm-chat-message[data-tail] .hjm-chat-message__bubble::before { transform: scaleX(-1); }
|
|
3430
|
+
.hjm-chat-message[data-tail][data-direction="outgoing"] .hjm-chat-message__bubble::before { inset-inline-start: auto; inset-inline-end: -6px; border-start-start-radius: 0; border-end-start-radius: 0; border-start-end-radius: 1px; border-end-end-radius: 10px; background: var(--hjm-color-surface-accent); }
|
|
3431
|
+
/* Logical corner radii and insets mirror the curved tail in RTL. */
|
|
3407
3432
|
|
|
3408
3433
|
.hjm-chat-message__meta { display: flex; flex-shrink: 0; align-items: center; gap: var(--hjm-space-xs); }
|
|
3409
3434
|
/* Reaction summary pill (sizes inline from chatMessageRecipe.reactionSummary); own reaction shows the brand border. */
|
|
@@ -3592,11 +3617,12 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
|
|
|
3592
3617
|
/* Keep the inset pill behind the whole line at large text (40px text / 28px fill was observed). Native already includes this inset as vertical padding. */
|
|
3593
3618
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__items { flex-wrap:wrap; gap:var(--hjm-space-xs); overflow:visible; padding:0; border:0; border-radius:0; background:transparent; }
|
|
3594
3619
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item { padding-block:var(--hjm-space-xxs); position:relative; flex:0 1 auto; min-inline-size:0; min-block-size:max(var(--hjm-control-min-touch-target), calc(var(--hjm-segmented-height) + 2 * var(--hjm-space-xxs))); border:0; border-radius:var(--hjm-radius-full); background:transparent; box-shadow:none; padding-inline:var(--hjm-space-md); color:var(--hjm-color-text-muted); }
|
|
3595
|
-
|
|
3620
|
+
/* Outline the inset surface, preserving the pill's layout and touch target on colored scenes. */
|
|
3621
|
+
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item::before { content:""; position:absolute; inset:var(--hjm-space-xxs) 0; border-radius:var(--hjm-radius-full); background:var(--hjm-color-bg); border:1px solid var(--hjm-color-border-control); }
|
|
3596
3622
|
.hjm-segmented[data-presentation="pills"][data-size="small"] .hjm-segmented__item { padding-inline:var(--hjm-space-sm); }
|
|
3597
3623
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item > span { position:relative; overflow-wrap:anywhere; }
|
|
3598
3624
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"] { color:var(--hjm-color-bg); font-weight:var(--hjm-font-weight-semibold); }
|
|
3599
|
-
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"]::before { background:var(--hjm-color-text-body); }
|
|
3625
|
+
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"]::before { background:var(--hjm-color-text-body); border-color:var(--hjm-color-text-body); }
|
|
3600
3626
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item:focus-within { outline:2px solid var(--hjm-color-focus); outline-offset:2px; }
|
|
3601
3627
|
|
|
3602
3628
|
/* Reference rating: real radios preserve browser keyboard and form behavior. */
|
package/dist/styles.layered.css
CHANGED
|
@@ -1062,6 +1062,9 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
1062
1062
|
the avatar box in product styles. */
|
|
1063
1063
|
.hjm-list-row__leading { display: flex; align-items: center; justify-content: center; inline-size: var(--hjm-list-row-leading-size); block-size: var(--hjm-list-row-leading-size); overflow: hidden; }
|
|
1064
1064
|
.hjm-list-row__leading[data-shape="circle"] { border-radius: var(--hjm-radius-full); }
|
|
1065
|
+
/* Photo source peers share ListRow geometry; only their decorative brand plate is specialized. */
|
|
1066
|
+
.hjm-photo-source__icon { display: grid; place-items: center; inline-size: 100%; block-size: 100%; border-radius: var(--hjm-radius-md); }
|
|
1067
|
+
.hjm-photo-source__icon svg { inline-size: 24px; block-size: 24px; }
|
|
1065
1068
|
.hjm-list-row__content { flex: 1 1 auto; min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
|
|
1066
1069
|
/* listRowRecipe title bodyLarge / description body (2026-10-17: Web inherited 14 for both while Native used the recipe). */
|
|
1067
1070
|
.hjm-list-row__title { 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; }
|
|
@@ -2384,7 +2387,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2384
2387
|
display: flex;
|
|
2385
2388
|
flex-wrap: wrap;
|
|
2386
2389
|
justify-content: flex-end;
|
|
2387
|
-
|
|
2390
|
+
/* Match actionGroupRecipe: 8px in either direction (2026-10-20 user request). */
|
|
2391
|
+
gap: var(--hjm-space-xs);
|
|
2388
2392
|
padding: 0 var(--hjm-space-lg) var(--hjm-space-lg);
|
|
2389
2393
|
}
|
|
2390
2394
|
.hjm-dialog__close {
|
|
@@ -2676,6 +2680,27 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
2676
2680
|
.hjm-menu__leading,
|
|
2677
2681
|
.hjm-menu__trailing { flex: 0 0 auto; color: var(--hjm-color-text-muted); }
|
|
2678
2682
|
|
|
2683
|
+
/* Three Menu presentations share items and focus semantics; modal chrome never belongs to a consumer. */
|
|
2684
|
+
.hjm-menu-positioner[data-presentation="bottom"] { align-items: end; padding-block-end: max(var(--hjm-space-md), env(safe-area-inset-bottom)); }
|
|
2685
|
+
.hjm-menu__content[data-presentation="grouped"],
|
|
2686
|
+
.hjm-menu__content[data-presentation="bottom"] {
|
|
2687
|
+
position: relative; inset: auto; display: flex; flex-direction: column; gap: var(--hjm-space-xs);
|
|
2688
|
+
inline-size: min(18rem, 100%); min-inline-size: 0; max-inline-size: 100%;
|
|
2689
|
+
max-block-size: calc(100dvh - 2 * var(--hjm-space-md)); padding: var(--hjm-space-sm);
|
|
2690
|
+
border-radius: var(--hjm-radius-lg);
|
|
2691
|
+
}
|
|
2692
|
+
.hjm-menu__content[data-presentation="bottom"] { inline-size: min(26.25rem, 100%); padding: 0; border: 0; background: transparent; box-shadow: none; }
|
|
2693
|
+
.hjm-menu__content[data-presentation="bottom"] .hjm-menu__viewport { background: var(--hjm-color-bg); }
|
|
2694
|
+
.hjm-menu__content[data-presentation="grouped"] .hjm-menu__viewport,
|
|
2695
|
+
.hjm-menu__content[data-presentation="bottom"] .hjm-menu__viewport { min-block-size: 0; overflow: auto; border-radius: var(--hjm-radius-md); }
|
|
2696
|
+
.hjm-menu__content[data-presentation="grouped"] .hjm-menu__viewport { background: var(--hjm-color-surface); }
|
|
2697
|
+
.hjm-menu__content[data-presentation="anchored"] .hjm-menu__item + .hjm-menu__item,
|
|
2698
|
+
.hjm-menu__content[data-presentation="grouped"] .hjm-menu__item + .hjm-menu__item,
|
|
2699
|
+
.hjm-menu__content[data-presentation="bottom"] .hjm-menu__item + .hjm-menu__item { border-block-start: 1px solid var(--hjm-color-border); border-radius: 0; }
|
|
2700
|
+
.hjm-menu__content[data-presentation="grouped"][data-density="comfortable"] .hjm-menu__item { min-block-size: 3.25rem; }
|
|
2701
|
+
.hjm-menu__content[data-presentation="grouped"] > .hjm-button,
|
|
2702
|
+
.hjm-menu__content[data-presentation="bottom"] > .hjm-button { flex-shrink: 0; inline-size: 100%; }
|
|
2703
|
+
|
|
2679
2704
|
/* Advanced forms --------------------------------------------------------- */
|
|
2680
2705
|
.hjm-select__native { appearance: none; padding-inline-end: calc(var(--hjm-space-lg) + var(--hjm-space-sm)); cursor: pointer; }
|
|
2681
2706
|
.hjm-select__anchor { position: relative; min-inline-size: 0; }
|
|
@@ -3398,13 +3423,13 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
|
|
|
3398
3423
|
.hjm-chat-message[data-direction="outgoing"] .hjm-chat-message__body { flex-direction: row-reverse; }
|
|
3399
3424
|
.hjm-chat-message__bubble { border-radius: 14px; background: var(--hjm-color-surface); padding: 6px 10px; min-inline-size: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
|
|
3400
3425
|
.hjm-chat-message[data-direction="outgoing"] .hjm-chat-message__bubble { background: var(--hjm-color-surface-accent); }
|
|
3401
|
-
/*
|
|
3426
|
+
/* Tighten the first corner to join the overlapping rounded tip. */
|
|
3402
3427
|
.hjm-chat-message[data-tail] .hjm-chat-message__bubble { position: relative; border-start-start-radius: 4px; }
|
|
3403
|
-
|
|
3428
|
+
/* The reference tip follows the top edge; its curved underside joins the bubble (2026-10-20). */
|
|
3429
|
+
.hjm-chat-message[data-tail] .hjm-chat-message__bubble::before { content: ""; position: absolute; top: 0; inset-inline-start: -6px; width: 11px; height: 10px; border-start-start-radius: 1px; border-end-start-radius: 10px; background: var(--hjm-color-surface); pointer-events: none; }
|
|
3404
3430
|
.hjm-chat-message[data-tail][data-direction="outgoing"] .hjm-chat-message__bubble { border-start-start-radius: 14px; border-start-end-radius: 4px; }
|
|
3405
|
-
.hjm-chat-message[data-tail][data-direction="outgoing"] .hjm-chat-message__bubble::before { inset-inline-start: auto; inset-inline-end: -6px;
|
|
3406
|
-
/*
|
|
3407
|
-
[dir="rtl"] .hjm-chat-message[data-tail] .hjm-chat-message__bubble::before { transform: scaleX(-1); }
|
|
3431
|
+
.hjm-chat-message[data-tail][data-direction="outgoing"] .hjm-chat-message__bubble::before { inset-inline-start: auto; inset-inline-end: -6px; border-start-start-radius: 0; border-end-start-radius: 0; border-start-end-radius: 1px; border-end-end-radius: 10px; background: var(--hjm-color-surface-accent); }
|
|
3432
|
+
/* Logical corner radii and insets mirror the curved tail in RTL. */
|
|
3408
3433
|
|
|
3409
3434
|
.hjm-chat-message__meta { display: flex; flex-shrink: 0; align-items: center; gap: var(--hjm-space-xs); }
|
|
3410
3435
|
/* Reaction summary pill (sizes inline from chatMessageRecipe.reactionSummary); own reaction shows the brand border. */
|
|
@@ -3593,11 +3618,12 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
|
|
|
3593
3618
|
/* Keep the inset pill behind the whole line at large text (40px text / 28px fill was observed). Native already includes this inset as vertical padding. */
|
|
3594
3619
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__items { flex-wrap:wrap; gap:var(--hjm-space-xs); overflow:visible; padding:0; border:0; border-radius:0; background:transparent; }
|
|
3595
3620
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item { padding-block:var(--hjm-space-xxs); position:relative; flex:0 1 auto; min-inline-size:0; min-block-size:max(var(--hjm-control-min-touch-target), calc(var(--hjm-segmented-height) + 2 * var(--hjm-space-xxs))); border:0; border-radius:var(--hjm-radius-full); background:transparent; box-shadow:none; padding-inline:var(--hjm-space-md); color:var(--hjm-color-text-muted); }
|
|
3596
|
-
|
|
3621
|
+
/* Outline the inset surface, preserving the pill's layout and touch target on colored scenes. */
|
|
3622
|
+
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item::before { content:""; position:absolute; inset:var(--hjm-space-xxs) 0; border-radius:var(--hjm-radius-full); background:var(--hjm-color-bg); border:1px solid var(--hjm-color-border-control); }
|
|
3597
3623
|
.hjm-segmented[data-presentation="pills"][data-size="small"] .hjm-segmented__item { padding-inline:var(--hjm-space-sm); }
|
|
3598
3624
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item > span { position:relative; overflow-wrap:anywhere; }
|
|
3599
3625
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"] { color:var(--hjm-color-bg); font-weight:var(--hjm-font-weight-semibold); }
|
|
3600
|
-
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"]::before { background:var(--hjm-color-text-body); }
|
|
3626
|
+
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item[data-state="checked"]::before { background:var(--hjm-color-text-body); border-color:var(--hjm-color-text-body); }
|
|
3601
3627
|
.hjm-segmented[data-presentation="pills"] .hjm-segmented__item:focus-within { outline:2px solid var(--hjm-color-focus); outline-offset:2px; }
|
|
3602
3628
|
|
|
3603
3629
|
/* Reference rating: real radios preserve browser keyboard and form behavior. */
|
|
@@ -4,6 +4,8 @@ import { type HTMLAttributes } from "react";
|
|
|
4
4
|
import type { HjmCompositionStyleProp } from "./composition-style.js";
|
|
5
5
|
export type LoadMoreProps = Omit<HTMLAttributes<HTMLDivElement>, "children"> & Readonly<{
|
|
6
6
|
descriptor: LoadMoreDescriptor;
|
|
7
|
+
/** Product mutation/refetch lock, separate from the next-page loading state. */
|
|
8
|
+
disabled?: boolean;
|
|
7
9
|
mode?: LoadMoreMode;
|
|
8
10
|
density?: LoadMoreDensity;
|
|
9
11
|
onLoadMore: LoadMoreRequestHandler;
|
|
@@ -20,6 +22,8 @@ export type LoadMoreProps = Omit<HTMLAttributes<HTMLDivElement>, "children"> & R
|
|
|
20
22
|
*/
|
|
21
23
|
export declare const LoadMore: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children"> & Readonly<{
|
|
22
24
|
descriptor: LoadMoreDescriptor;
|
|
25
|
+
/** Product mutation/refetch lock, separate from the next-page loading state. */
|
|
26
|
+
disabled?: boolean;
|
|
23
27
|
mode?: LoadMoreMode;
|
|
24
28
|
density?: LoadMoreDensity;
|
|
25
29
|
onLoadMore: LoadMoreRequestHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supplemental-navigation.d.ts","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AA8BtE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAC1E,QAAQ,CAAC;IACP,UAAU,EAAE,kBAAkB,CAAC;IAC/B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,sBAAsB,CAAC;IACnC,gBAAgB,CAAC,EAAE,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI,CAAC;IACV,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACzE,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,QAAQ;
|
|
1
|
+
{"version":3,"file":"supplemental-navigation.d.ts","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AA8BtE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAC1E,QAAQ,CAAC;IACP,UAAU,EAAE,kBAAkB,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,sBAAsB,CAAC;IACnC,gBAAgB,CAAC,EAAE,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI,CAAC;IACV,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACzE,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,QAAQ;gBArBL,kBAAkB;IAC9B,gFAAgF;eACrE,OAAO;WACX,YAAY;cACT,eAAe;gBACb,sBAAsB;uBACf,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI;qBACQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI;uBACrD,OAAO,GAAG,QAAQ,GAAG,IAAI;iBAC/B,MAAM;IACnB,gGAAgG;kBAClF,uBAAuB;mDA+JxC,CAAC"}
|
|
@@ -33,8 +33,10 @@ function createLoadMoreControllerFacade() {
|
|
|
33
33
|
* A collection footer that keeps product data controlled while the shared
|
|
34
34
|
* controller prevents overlapping cursor requests.
|
|
35
35
|
*/
|
|
36
|
-
export const LoadMore = forwardRef(function LoadMore({ descriptor, mode = loadMoreRecipe.defaults.mode, density = loadMoreRecipe.defaults.density, onLoadMore, onRequestOutcome, onRequestError, intersectionRoot = null, rootMargin = "200px 0px", className, layoutStyle, style, ...props }, ref) {
|
|
36
|
+
export const LoadMore = forwardRef(function LoadMore({ descriptor, disabled = false, mode = loadMoreRecipe.defaults.mode, density = loadMoreRecipe.defaults.density, onLoadMore, onRequestOutcome, onRequestError, intersectionRoot = null, rootMargin = "200px 0px", className, layoutStyle, style, ...props }, ref) {
|
|
37
37
|
validateLoadMoreDescriptor(descriptor);
|
|
38
|
+
const disabledRef = useRef(disabled);
|
|
39
|
+
disabledRef.current = disabled;
|
|
38
40
|
const onLoadMoreRef = useRef(onLoadMore);
|
|
39
41
|
onLoadMoreRef.current = onLoadMore;
|
|
40
42
|
const [controllerFacade] = useState(createLoadMoreControllerFacade);
|
|
@@ -51,7 +53,7 @@ export const LoadMore = forwardRef(function LoadMore({ descriptor, mode = loadMo
|
|
|
51
53
|
return () => { currentRequestIdentityRef.current = null; };
|
|
52
54
|
}, [currentRequestIdentity]);
|
|
53
55
|
const request = useCallback(async (state, reason) => {
|
|
54
|
-
if (state.status === "loading" || state.status === "complete")
|
|
56
|
+
if (disabledRef.current || state.status === "loading" || state.status === "complete")
|
|
55
57
|
return;
|
|
56
58
|
const requestIdentity = `${state.status}:${state.requestKey}`;
|
|
57
59
|
// IntersectionObserver may deliver an already queued callback after
|
|
@@ -93,7 +95,7 @@ export const LoadMore = forwardRef(function LoadMore({ descriptor, mode = loadMo
|
|
|
93
95
|
};
|
|
94
96
|
}, [controllerFacade, mode]);
|
|
95
97
|
useEffect(() => {
|
|
96
|
-
if (mode !== "automatic" ||
|
|
98
|
+
if (disabled || mode !== "automatic" ||
|
|
97
99
|
descriptor.state.status !== "ready" ||
|
|
98
100
|
typeof IntersectionObserver === "undefined") {
|
|
99
101
|
return;
|
|
@@ -108,8 +110,8 @@ export const LoadMore = forwardRef(function LoadMore({ descriptor, mode = loadMo
|
|
|
108
110
|
}, { root: intersectionRoot, rootMargin });
|
|
109
111
|
observer.observe(sentinel);
|
|
110
112
|
return () => observer.disconnect();
|
|
111
|
-
}, [descriptor.state, intersectionRoot, mode, request, rootMargin]);
|
|
113
|
+
}, [descriptor.state, disabled, intersectionRoot, mode, request, rootMargin]);
|
|
112
114
|
const { state, labels } = descriptor;
|
|
113
|
-
return (_jsxs("div", { ...props, style: { ...style, ...layoutStyle }, ref: ref, className: classNames("hjm-load-more", className), "data-mode": mode, "data-density": density, "data-state": state.status, "aria-busy": state.status === "loading" || undefined, children: [_jsx("span", { ref: sentinelRef, className: "hjm-load-more__sentinel", "aria-hidden": "true" }), state.status === "ready" ? (_jsx("button", { type: "button", className: "hjm-load-more__trigger", onClick: () => void request(state, "manual"), children: labels.loadMore })) : state.status === "loading" ? (_jsxs("div", { className: "hjm-load-more__status", role: "status", children: [_jsx("span", { className: "hjm-load-more__spinner", "aria-hidden": "true" }), _jsx("span", { className: "hjm-visually-hidden", children: labels.loading })] })) : state.status === "error" ? (_jsxs("div", { className: "hjm-load-more__error", children: [_jsx("span", { role: "alert", children: state.message }), _jsx("button", { type: "button", className: "hjm-load-more__trigger", onClick: () => void request(state, "retry"), children: labels.retry })] })) : (_jsx("div", { className: "hjm-load-more__end", children: labels.complete }))] }));
|
|
115
|
+
return (_jsxs("div", { ...props, style: { ...style, ...layoutStyle }, ref: ref, className: classNames("hjm-load-more", className), "data-mode": mode, "data-density": density, "data-state": state.status, "aria-disabled": disabled || undefined, "aria-busy": state.status === "loading" || undefined, children: [_jsx("span", { ref: sentinelRef, className: "hjm-load-more__sentinel", "aria-hidden": "true" }), state.status === "ready" ? (_jsx("button", { type: "button", className: "hjm-load-more__trigger", disabled: disabled, onClick: () => void request(state, "manual"), children: labels.loadMore })) : state.status === "loading" ? (_jsxs("div", { className: "hjm-load-more__status", role: "status", children: [_jsx("span", { className: "hjm-load-more__spinner", "aria-hidden": "true" }), _jsx("span", { className: "hjm-visually-hidden", children: labels.loading })] })) : state.status === "error" ? (_jsxs("div", { className: "hjm-load-more__error", children: [_jsx("span", { role: "alert", children: state.message }), _jsx("button", { type: "button", className: "hjm-load-more__trigger", disabled: disabled, onClick: () => void request(state, "retry"), children: labels.retry })] })) : (_jsx("div", { className: "hjm-load-more__end", children: labels.complete }))] }));
|
|
114
116
|
});
|
|
115
117
|
//# sourceMappingURL=supplemental-navigation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supplemental-navigation.js","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createLoadMoreController,\n validateLoadMoreDescriptor,\n type LoadMoreController,\n type LoadMoreControllerSnapshot,\n type LoadMoreDescriptor,\n type LoadMoreMode,\n type LoadMoreRequestHandler,\n type LoadMoreRequestOutcome,\n type LoadMoreRequestReason,\n} from \"@hjmds/design-contracts/components/load-more\";\nimport {\n loadMoreRecipe,\n type LoadMoreDensity,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type HTMLAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nfunction createLoadMoreControllerFacade(): Readonly<{\n facade: LoadMoreController;\n attach(controller: LoadMoreController): () => void;\n}> {\n const detachedSnapshot: LoadMoreControllerSnapshot = {\n mode: \"automatic\",\n inFlightRequestKey: null,\n disposed: true,\n };\n let active: LoadMoreController | null = null;\n return {\n facade: {\n getSnapshot: () => active?.getSnapshot() ?? detachedSnapshot,\n request: (state, reason) => {\n if (!active) throw new Error(\"Cannot use a detached LoadMore controller\");\n return active.request(state, reason);\n },\n dispose: () => active?.dispose() ?? false,\n },\n attach(controller) {\n active = controller;\n return () => {\n if (active === controller) active = null;\n };\n },\n };\n}\n\nexport type LoadMoreProps = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> &\n Readonly<{\n descriptor: LoadMoreDescriptor;\n mode?: LoadMoreMode;\n density?: LoadMoreDensity;\n onLoadMore: LoadMoreRequestHandler;\n onRequestOutcome?: (\n outcome: LoadMoreRequestOutcome,\n reason: LoadMoreRequestReason,\n ) => void;\n onRequestError?: (error: unknown, reason: LoadMoreRequestReason) => void;\n intersectionRoot?: Element | Document | null;\n rootMargin?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\n/**\n * A collection footer that keeps product data controlled while the shared\n * controller prevents overlapping cursor requests.\n */\nexport const LoadMore = forwardRef<HTMLDivElement, LoadMoreProps>(\n function LoadMore(\n {\n descriptor,\n mode = loadMoreRecipe.defaults.mode,\n density = loadMoreRecipe.defaults.density,\n onLoadMore,\n onRequestOutcome,\n onRequestError,\n intersectionRoot = null,\n rootMargin = \"200px 0px\",\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n ) {\n validateLoadMoreDescriptor(descriptor);\n const onLoadMoreRef = useRef(onLoadMore);\n onLoadMoreRef.current = onLoadMore;\n const [controllerFacade] = useState(createLoadMoreControllerFacade);\n const controller = controllerFacade.facade;\n const requestGeneration = useRef(0);\n const sentinelRef = useRef<HTMLSpanElement>(null);\n const currentRequestIdentityRef = useRef<string | null>(null);\n const completedRequestIdentityRef = useRef<string | null>(null);\n const currentRequestIdentity =\n descriptor.state.status === \"ready\" || descriptor.state.status === \"error\"\n ? `${descriptor.state.status}:${descriptor.state.requestKey}`\n : null;\n\n useLayoutEffect(() => {\n currentRequestIdentityRef.current = currentRequestIdentity;\n return () => { currentRequestIdentityRef.current = null; };\n }, [currentRequestIdentity]);\n\n const request = useCallback(\n async (\n state: LoadMoreDescriptor[\"state\"],\n reason: LoadMoreRequestReason,\n ) => {\n if (state.status === \"loading\" || state.status === \"complete\") return;\n const requestIdentity = `${state.status}:${state.requestKey}`;\n // IntersectionObserver may deliver an already queued callback after\n // disconnect. Only events for the currently committed descriptor may\n // enter the shared request controller.\n if (currentRequestIdentityRef.current !== requestIdentity) return;\n // Once a request settles successfully, retire that exact state/key\n // until the product commits a new cursor or a retryable error state.\n if (completedRequestIdentityRef.current === requestIdentity) return;\n const generation = requestGeneration.current;\n try {\n const outcome = await controller.request(state, reason);\n if (generation !== requestGeneration.current) return;\n if (outcome === \"started\") {\n completedRequestIdentityRef.current = requestIdentity;\n }\n onRequestOutcome?.(outcome, reason);\n } catch (error) {\n if (generation === requestGeneration.current) onRequestError?.(error, reason);\n }\n },\n [controller, onRequestError, onRequestOutcome],\n );\n\n useEffect(() => {\n const attached = createLoadMoreController({\n mode,\n onLoadMore: (nextRequest) => onLoadMoreRef.current(nextRequest),\n });\n const detach = controllerFacade.attach(attached);\n requestGeneration.current += 1;\n return () => {\n // The query remains product-owned; only this retired footer's callbacks stop.\n requestGeneration.current += 1;\n detach();\n attached.dispose();\n };\n }, [controllerFacade, mode]);\n\n useEffect(() => {\n if (\n mode !== \"automatic\" ||\n descriptor.state.status !== \"ready\" ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n void request(descriptor.state, \"viewport\");\n }\n },\n { root: intersectionRoot, rootMargin },\n );\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [descriptor.state, intersectionRoot, mode, request, rootMargin]);\n\n const { state, labels } = descriptor;\n return (\n <div\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-load-more\", className)}\n data-mode={mode}\n data-density={density}\n data-state={state.status}\n aria-busy={state.status === \"loading\" || undefined}\n >\n <span ref={sentinelRef} className=\"hjm-load-more__sentinel\" aria-hidden=\"true\" />\n {state.status === \"ready\" ? (\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n onClick={() => void request(state, \"manual\")}\n >\n {labels.loadMore}\n </button>\n ) : state.status === \"loading\" ? (\n <div className=\"hjm-load-more__status\" role=\"status\">\n <span className=\"hjm-load-more__spinner\" aria-hidden=\"true\" />\n <span className=\"hjm-visually-hidden\">{labels.loading}</span>\n </div>\n ) : state.status === \"error\" ? (\n <div className=\"hjm-load-more__error\">\n <span role=\"alert\">{state.message}</span>\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n onClick={() => void request(state, \"retry\")}\n >\n {labels.retry}\n </button>\n </div>\n ) : (\n <div className=\"hjm-load-more__end\">{labels.complete}</div>\n )}\n </div>\n );\n },\n);\n"]}
|
|
1
|
+
{"version":3,"file":"supplemental-navigation.js","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createLoadMoreController,\n validateLoadMoreDescriptor,\n type LoadMoreController,\n type LoadMoreControllerSnapshot,\n type LoadMoreDescriptor,\n type LoadMoreMode,\n type LoadMoreRequestHandler,\n type LoadMoreRequestOutcome,\n type LoadMoreRequestReason,\n} from \"@hjmds/design-contracts/components/load-more\";\nimport {\n loadMoreRecipe,\n type LoadMoreDensity,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type HTMLAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nfunction createLoadMoreControllerFacade(): Readonly<{\n facade: LoadMoreController;\n attach(controller: LoadMoreController): () => void;\n}> {\n const detachedSnapshot: LoadMoreControllerSnapshot = {\n mode: \"automatic\",\n inFlightRequestKey: null,\n disposed: true,\n };\n let active: LoadMoreController | null = null;\n return {\n facade: {\n getSnapshot: () => active?.getSnapshot() ?? detachedSnapshot,\n request: (state, reason) => {\n if (!active) throw new Error(\"Cannot use a detached LoadMore controller\");\n return active.request(state, reason);\n },\n dispose: () => active?.dispose() ?? false,\n },\n attach(controller) {\n active = controller;\n return () => {\n if (active === controller) active = null;\n };\n },\n };\n}\n\nexport type LoadMoreProps = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> &\n Readonly<{\n descriptor: LoadMoreDescriptor;\n /** Product mutation/refetch lock, separate from the next-page loading state. */\n disabled?: boolean;\n mode?: LoadMoreMode;\n density?: LoadMoreDensity;\n onLoadMore: LoadMoreRequestHandler;\n onRequestOutcome?: (\n outcome: LoadMoreRequestOutcome,\n reason: LoadMoreRequestReason,\n ) => void;\n onRequestError?: (error: unknown, reason: LoadMoreRequestReason) => void;\n intersectionRoot?: Element | Document | null;\n rootMargin?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\n/**\n * A collection footer that keeps product data controlled while the shared\n * controller prevents overlapping cursor requests.\n */\nexport const LoadMore = forwardRef<HTMLDivElement, LoadMoreProps>(\n function LoadMore(\n {\n descriptor,\n disabled = false,\n mode = loadMoreRecipe.defaults.mode,\n density = loadMoreRecipe.defaults.density,\n onLoadMore,\n onRequestOutcome,\n onRequestError,\n intersectionRoot = null,\n rootMargin = \"200px 0px\",\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n ) {\n validateLoadMoreDescriptor(descriptor);\n const disabledRef = useRef(disabled);\n disabledRef.current = disabled;\n const onLoadMoreRef = useRef(onLoadMore);\n onLoadMoreRef.current = onLoadMore;\n const [controllerFacade] = useState(createLoadMoreControllerFacade);\n const controller = controllerFacade.facade;\n const requestGeneration = useRef(0);\n const sentinelRef = useRef<HTMLSpanElement>(null);\n const currentRequestIdentityRef = useRef<string | null>(null);\n const completedRequestIdentityRef = useRef<string | null>(null);\n const currentRequestIdentity =\n descriptor.state.status === \"ready\" || descriptor.state.status === \"error\"\n ? `${descriptor.state.status}:${descriptor.state.requestKey}`\n : null;\n\n useLayoutEffect(() => {\n currentRequestIdentityRef.current = currentRequestIdentity;\n return () => { currentRequestIdentityRef.current = null; };\n }, [currentRequestIdentity]);\n\n const request = useCallback(\n async (\n state: LoadMoreDescriptor[\"state\"],\n reason: LoadMoreRequestReason,\n ) => {\n if (disabledRef.current || state.status === \"loading\" || state.status === \"complete\") return;\n const requestIdentity = `${state.status}:${state.requestKey}`;\n // IntersectionObserver may deliver an already queued callback after\n // disconnect. Only events for the currently committed descriptor may\n // enter the shared request controller.\n if (currentRequestIdentityRef.current !== requestIdentity) return;\n // Once a request settles successfully, retire that exact state/key\n // until the product commits a new cursor or a retryable error state.\n if (completedRequestIdentityRef.current === requestIdentity) return;\n const generation = requestGeneration.current;\n try {\n const outcome = await controller.request(state, reason);\n if (generation !== requestGeneration.current) return;\n if (outcome === \"started\") {\n completedRequestIdentityRef.current = requestIdentity;\n }\n onRequestOutcome?.(outcome, reason);\n } catch (error) {\n if (generation === requestGeneration.current) onRequestError?.(error, reason);\n }\n },\n [controller, onRequestError, onRequestOutcome],\n );\n\n useEffect(() => {\n const attached = createLoadMoreController({\n mode,\n onLoadMore: (nextRequest) => onLoadMoreRef.current(nextRequest),\n });\n const detach = controllerFacade.attach(attached);\n requestGeneration.current += 1;\n return () => {\n // The query remains product-owned; only this retired footer's callbacks stop.\n requestGeneration.current += 1;\n detach();\n attached.dispose();\n };\n }, [controllerFacade, mode]);\n\n useEffect(() => {\n if (\n disabled || mode !== \"automatic\" ||\n descriptor.state.status !== \"ready\" ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n void request(descriptor.state, \"viewport\");\n }\n },\n { root: intersectionRoot, rootMargin },\n );\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [descriptor.state, disabled, intersectionRoot, mode, request, rootMargin]);\n\n const { state, labels } = descriptor;\n return (\n <div\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-load-more\", className)}\n data-mode={mode}\n data-density={density}\n data-state={state.status}\n aria-disabled={disabled || undefined}\n aria-busy={state.status === \"loading\" || undefined}\n >\n <span ref={sentinelRef} className=\"hjm-load-more__sentinel\" aria-hidden=\"true\" />\n {state.status === \"ready\" ? (\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n disabled={disabled}\n onClick={() => void request(state, \"manual\")}\n >\n {labels.loadMore}\n </button>\n ) : state.status === \"loading\" ? (\n <div className=\"hjm-load-more__status\" role=\"status\">\n <span className=\"hjm-load-more__spinner\" aria-hidden=\"true\" />\n <span className=\"hjm-visually-hidden\">{labels.loading}</span>\n </div>\n ) : state.status === \"error\" ? (\n <div className=\"hjm-load-more__error\">\n <span role=\"alert\">{state.message}</span>\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n disabled={disabled}\n onClick={() => void request(state, \"retry\")}\n >\n {labels.retry}\n </button>\n </div>\n ) : (\n <div className=\"hjm-load-more__end\">{labels.complete}</div>\n )}\n </div>\n );\n },\n);\n"]}
|
package/dist/task-controls.js
CHANGED
|
@@ -17,7 +17,7 @@ function ChoiceMenu(props) {
|
|
|
17
17
|
if (!available)
|
|
18
18
|
return _jsx(Button, { disabled: true, children: props.label });
|
|
19
19
|
const trigger = props.trigger === "icon" ? _jsx(IconButton, { label: props.label, tone: "secondary", children: _jsx(Icon, { name: "chevronDown" }) }) : _jsx(Button, { tone: "secondary", loading: props.pending === true, children: props.label });
|
|
20
|
-
return _jsx(Menu, { label: props.label, trigger: trigger, disabled: props.disabled, items: props.choices, selectionMode: "single", value: props.selectedId, onValueChange: () => undefined, onActionAfterDismiss: props.onChoose });
|
|
20
|
+
return _jsx(Menu, { presentation: "anchored", label: props.label, trigger: trigger, disabled: props.disabled, items: props.choices, selectionMode: "single", value: props.selectedId, onValueChange: () => undefined, onActionAfterDismiss: props.onChoose });
|
|
21
21
|
}
|
|
22
22
|
function Failure({ failed, label }) {
|
|
23
23
|
return failed ? _jsx(Text, { role: "alert", tone: "danger", style: { textAlign: "center" }, children: label }) : null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-controls.js","sourceRoot":"","sources":["../src/task-controls.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport { resolveTaskChoice, resolvePasswordRules, resolvePriceOption, type TaskChoice, type PasswordRule, type PriceOption } from \"@hjmds/design-contracts/task-controls\";\nimport { Button, IconButton } from \"./actions.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { Menu } from \"./overlays.js\";\nimport { PasswordField, type PasswordFieldProps } from \"./forms.js\";\nimport { RadioGroup } from \"./selection.js\";\nimport { Card } from \"./display.js\";\nimport { Progress } from \"./feedback.js\";\nimport { Stack, Text } from \"./layout.js\";\nimport { useCompositionAction } from \"./internal/use-composition-action.js\";\n\ntype ChoiceMenuProps = Readonly<{ choices: readonly TaskChoice[]; selectedId: string; label: string; dismissLabel: string; disabled: boolean; pending?: boolean; onChoose: (id: string) => void;\n /** `icon`: a chevron tool beside the action it modifies (SplitAction); the label stays the accessible name. */\n trigger?: \"text\" | \"icon\" }>;\nfunction ChoiceMenu(props: ChoiceMenuProps) {\n const available = props.choices.some(choice => !choice.disabled);\n if (props.trigger === \"icon\" && !available) return <IconButton label={props.label} tone=\"secondary\" disabled><Icon name=\"chevronDown\" /></IconButton>;\n if (!available) return <Button disabled>{props.label}</Button>;\n const trigger = props.trigger === \"icon\" ? <IconButton label={props.label} tone=\"secondary\"><Icon name=\"chevronDown\" /></IconButton> : <Button tone=\"secondary\" loading={props.pending === true}>{props.label}</Button>;\n return <Menu label={props.label} trigger={trigger} disabled={props.disabled}\n items={props.choices} selectionMode=\"single\" value={props.selectedId} onValueChange={() => undefined} onActionAfterDismiss={props.onChoose} />;\n}\nfunction Failure({ failed, label }: Readonly<{ failed: boolean; label: string }>) {\n return failed ? <Text role=\"alert\" tone=\"danger\" style={{ textAlign: \"center\" }}>{label}</Text> : null;\n}\n\nexport type SplitActionProps = Readonly<{\n modes: readonly TaskChoice[]; modeId: string; onModeChange: (id: string) => void;\n onExecute: (modeId: string) => void | Promise<void>; executeLabel: (mode: TaskChoice) => string;\n menuLabel: string; dismissLabel: string; errorLabel: string; disabled?: boolean;\n}>;\nexport function SplitAction(props: SplitActionProps) {\n const mode = resolveTaskChoice(props.modes, props.modeId), action = useCompositionAction(props.disabled);\n const locked = props.disabled === true || action.pending;\n // The mode menu is a chevron tool at the action's end, inline gap 12 (button.md); a second text button read as an unrelated action (2026-10-17 review).\n return <Stack gap=\"sm\"><Stack axis=\"inline\" gap=\"sm\" align=\"center\">\n <Button loading={action.pending} disabled={props.disabled === true || mode.disabled === true} onClick={() => { if (!mode.disabled) void action.run(mode.id, () => props.onExecute(mode.id)); }}>{props.executeLabel(mode)}</Button>\n <ChoiceMenu trigger=\"icon\" choices={props.modes} selectedId={mode.id} label={props.menuLabel} dismissLabel={props.dismissLabel} disabled={locked} onChoose={id => { if (!locked && !resolveTaskChoice(props.modes, id).disabled) props.onModeChange(id); }} />\n </Stack><Failure failed={action.failed} label={props.errorLabel} /></Stack>;\n}\n\nexport type AccountSwitcherProps = Readonly<{\n accounts: readonly TaskChoice[]; accountId: string; label: string; dismissLabel: string; errorLabel: string;\n onSwitch: (accountId: string) => void | Promise<void>; disabled?: boolean;\n}>;\nexport function AccountSwitcher(props: AccountSwitcherProps) {\n const account = resolveTaskChoice(props.accounts, props.accountId), action = useCompositionAction(props.disabled);\n const locked = props.disabled === true || action.pending;\n // The controlled account stays confirmed until the product completes the session change.\n return <Stack gap=\"sm\"><Text emphasis=\"strong\">{account.label}</Text><ChoiceMenu choices={props.accounts} selectedId={account.id} label={props.label} dismissLabel={props.dismissLabel} disabled={locked} pending={action.pending}\n onChoose={id => { if (id !== account.id && !resolveTaskChoice(props.accounts, id).disabled) void action.run(id, () => props.onSwitch(id)); }} />\n <Failure failed={action.failed} label={props.errorLabel} /></Stack>;\n}\n\nexport type PasswordRulesFieldProps = Omit<PasswordFieldProps, \"value\" | \"defaultValue\" | \"onValueChange\"> & Readonly<{\n label: string; value: string; onValueChange: (value: string) => void; rules: readonly PasswordRule[];\n progressLabel: string; summaryLabel: (satisfied: number, total: number) => string;\n ruleLabel: (rule: ReturnType<typeof resolvePasswordRules>[\"rules\"][number]) => string;\n}>;\nexport function PasswordRulesField({ rules, progressLabel, summaryLabel, ruleLabel, ...field }: PasswordRulesFieldProps) {\n const state = resolvePasswordRules(field.value, rules);\n return <Stack gap=\"sm\"><PasswordField {...field} />\n <Progress label={progressLabel} value={state.satisfied} max={state.total} valueText={summaryLabel(state.satisfied, state.total)} />\n {state.rules.map(rule => <Text key={rule.id} variant=\"caption\" tone={rule.satisfied ? \"primary\" : \"muted\"}>{ruleLabel(rule)}</Text>)}\n </Stack>;\n}\n\nexport type PricingChoiceProps = Readonly<{\n label: string; options: readonly PriceOption[]; selectedId: string; onSelectionChange: (id: string) => void;\n formatPrice: (option: PriceOption) => string; continueLabel: string; errorLabel: string;\n onContinue: (option: PriceOption) => void | Promise<void>; disabled?: boolean;\n}>;\nexport function PricingChoice(props: PricingChoiceProps) {\n const option = resolvePriceOption(props.options, props.selectedId), action = useCompositionAction(props.disabled);\n const locked = props.disabled === true || action.pending;\n return <Card title={props.label}><Stack gap=\"md\"><RadioGroup accessibilityLabel={props.label} presentation=\"card\" value={option.id} disabled={locked}\n items={props.options.map(price => ({ value: price.id, label: price.label, description: props.formatPrice(price), disabled: price.disabled === true }))}\n onValueChange={id => { if (id !== null && !locked && !resolveTaskChoice(props.options, id).disabled) props.onSelectionChange(id); }} />\n <Text emphasis=\"strong\">{props.formatPrice(option)}</Text>\n {option.benefits.map((benefit, index) => <Text key={index}>{benefit}</Text>)}\n <Button loading={action.pending} disabled={props.disabled === true || option.disabled === true} onClick={() => { if (!option.disabled) void action.run(option.id, () => props.onContinue(Object.freeze({ ...option, benefits: Object.freeze([...option.benefits]) }))); }}>{props.continueLabel}</Button>\n <Failure failed={action.failed} label={props.errorLabel} /></Stack></Card>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"task-controls.js","sourceRoot":"","sources":["../src/task-controls.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport { resolveTaskChoice, resolvePasswordRules, resolvePriceOption, type TaskChoice, type PasswordRule, type PriceOption } from \"@hjmds/design-contracts/task-controls\";\nimport { Button, IconButton } from \"./actions.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { Menu } from \"./overlays.js\";\nimport { PasswordField, type PasswordFieldProps } from \"./forms.js\";\nimport { RadioGroup } from \"./selection.js\";\nimport { Card } from \"./display.js\";\nimport { Progress } from \"./feedback.js\";\nimport { Stack, Text } from \"./layout.js\";\nimport { useCompositionAction } from \"./internal/use-composition-action.js\";\n\ntype ChoiceMenuProps = Readonly<{ choices: readonly TaskChoice[]; selectedId: string; label: string; dismissLabel: string; disabled: boolean; pending?: boolean; onChoose: (id: string) => void;\n /** `icon`: a chevron tool beside the action it modifies (SplitAction); the label stays the accessible name. */\n trigger?: \"text\" | \"icon\" }>;\nfunction ChoiceMenu(props: ChoiceMenuProps) {\n const available = props.choices.some(choice => !choice.disabled);\n if (props.trigger === \"icon\" && !available) return <IconButton label={props.label} tone=\"secondary\" disabled><Icon name=\"chevronDown\" /></IconButton>;\n if (!available) return <Button disabled>{props.label}</Button>;\n const trigger = props.trigger === \"icon\" ? <IconButton label={props.label} tone=\"secondary\"><Icon name=\"chevronDown\" /></IconButton> : <Button tone=\"secondary\" loading={props.pending === true}>{props.label}</Button>;\n return <Menu presentation=\"anchored\" label={props.label} trigger={trigger} disabled={props.disabled}\n items={props.choices} selectionMode=\"single\" value={props.selectedId} onValueChange={() => undefined} onActionAfterDismiss={props.onChoose} />;\n}\nfunction Failure({ failed, label }: Readonly<{ failed: boolean; label: string }>) {\n return failed ? <Text role=\"alert\" tone=\"danger\" style={{ textAlign: \"center\" }}>{label}</Text> : null;\n}\n\nexport type SplitActionProps = Readonly<{\n modes: readonly TaskChoice[]; modeId: string; onModeChange: (id: string) => void;\n onExecute: (modeId: string) => void | Promise<void>; executeLabel: (mode: TaskChoice) => string;\n menuLabel: string; dismissLabel: string; errorLabel: string; disabled?: boolean;\n}>;\nexport function SplitAction(props: SplitActionProps) {\n const mode = resolveTaskChoice(props.modes, props.modeId), action = useCompositionAction(props.disabled);\n const locked = props.disabled === true || action.pending;\n // The mode menu is a chevron tool at the action's end, inline gap 12 (button.md); a second text button read as an unrelated action (2026-10-17 review).\n return <Stack gap=\"sm\"><Stack axis=\"inline\" gap=\"sm\" align=\"center\">\n <Button loading={action.pending} disabled={props.disabled === true || mode.disabled === true} onClick={() => { if (!mode.disabled) void action.run(mode.id, () => props.onExecute(mode.id)); }}>{props.executeLabel(mode)}</Button>\n <ChoiceMenu trigger=\"icon\" choices={props.modes} selectedId={mode.id} label={props.menuLabel} dismissLabel={props.dismissLabel} disabled={locked} onChoose={id => { if (!locked && !resolveTaskChoice(props.modes, id).disabled) props.onModeChange(id); }} />\n </Stack><Failure failed={action.failed} label={props.errorLabel} /></Stack>;\n}\n\nexport type AccountSwitcherProps = Readonly<{\n accounts: readonly TaskChoice[]; accountId: string; label: string; dismissLabel: string; errorLabel: string;\n onSwitch: (accountId: string) => void | Promise<void>; disabled?: boolean;\n}>;\nexport function AccountSwitcher(props: AccountSwitcherProps) {\n const account = resolveTaskChoice(props.accounts, props.accountId), action = useCompositionAction(props.disabled);\n const locked = props.disabled === true || action.pending;\n // The controlled account stays confirmed until the product completes the session change.\n return <Stack gap=\"sm\"><Text emphasis=\"strong\">{account.label}</Text><ChoiceMenu choices={props.accounts} selectedId={account.id} label={props.label} dismissLabel={props.dismissLabel} disabled={locked} pending={action.pending}\n onChoose={id => { if (id !== account.id && !resolveTaskChoice(props.accounts, id).disabled) void action.run(id, () => props.onSwitch(id)); }} />\n <Failure failed={action.failed} label={props.errorLabel} /></Stack>;\n}\n\nexport type PasswordRulesFieldProps = Omit<PasswordFieldProps, \"value\" | \"defaultValue\" | \"onValueChange\"> & Readonly<{\n label: string; value: string; onValueChange: (value: string) => void; rules: readonly PasswordRule[];\n progressLabel: string; summaryLabel: (satisfied: number, total: number) => string;\n ruleLabel: (rule: ReturnType<typeof resolvePasswordRules>[\"rules\"][number]) => string;\n}>;\nexport function PasswordRulesField({ rules, progressLabel, summaryLabel, ruleLabel, ...field }: PasswordRulesFieldProps) {\n const state = resolvePasswordRules(field.value, rules);\n return <Stack gap=\"sm\"><PasswordField {...field} />\n <Progress label={progressLabel} value={state.satisfied} max={state.total} valueText={summaryLabel(state.satisfied, state.total)} />\n {state.rules.map(rule => <Text key={rule.id} variant=\"caption\" tone={rule.satisfied ? \"primary\" : \"muted\"}>{ruleLabel(rule)}</Text>)}\n </Stack>;\n}\n\nexport type PricingChoiceProps = Readonly<{\n label: string; options: readonly PriceOption[]; selectedId: string; onSelectionChange: (id: string) => void;\n formatPrice: (option: PriceOption) => string; continueLabel: string; errorLabel: string;\n onContinue: (option: PriceOption) => void | Promise<void>; disabled?: boolean;\n}>;\nexport function PricingChoice(props: PricingChoiceProps) {\n const option = resolvePriceOption(props.options, props.selectedId), action = useCompositionAction(props.disabled);\n const locked = props.disabled === true || action.pending;\n return <Card title={props.label}><Stack gap=\"md\"><RadioGroup accessibilityLabel={props.label} presentation=\"card\" value={option.id} disabled={locked}\n items={props.options.map(price => ({ value: price.id, label: price.label, description: props.formatPrice(price), disabled: price.disabled === true }))}\n onValueChange={id => { if (id !== null && !locked && !resolveTaskChoice(props.options, id).disabled) props.onSelectionChange(id); }} />\n <Text emphasis=\"strong\">{props.formatPrice(option)}</Text>\n {option.benefits.map((benefit, index) => <Text key={index}>{benefit}</Text>)}\n <Button loading={action.pending} disabled={props.disabled === true || option.disabled === true} onClick={() => { if (!option.disabled) void action.run(option.id, () => props.onContinue(Object.freeze({ ...option, benefits: Object.freeze([...option.benefits]) }))); }}>{props.continueLabel}</Button>\n <Failure failed={action.failed} label={props.errorLabel} /></Stack></Card>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hjmds/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.1",
|
|
4
4
|
"description": "Accessible React 19 renderers for HJM design contracts.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -608,7 +608,7 @@
|
|
|
608
608
|
"THIRD_PARTY_NOTICES.md"
|
|
609
609
|
],
|
|
610
610
|
"peerDependencies": {
|
|
611
|
-
"@hjmds/design-contracts": ">=1.
|
|
611
|
+
"@hjmds/design-contracts": ">=1.36.0 <1.37.0",
|
|
612
612
|
"react": ">=19.0.0",
|
|
613
613
|
"react-dom": ">=19.0.0",
|
|
614
614
|
"@number-flow/react": "0.6.2",
|
|
@@ -646,7 +646,7 @@
|
|
|
646
646
|
"@blobatar/react": "2.7.0",
|
|
647
647
|
"lucide-react": "1.59.0",
|
|
648
648
|
"vite": "8.3.4",
|
|
649
|
-
"@hjmds/design-contracts": "1.
|
|
649
|
+
"@hjmds/design-contracts": "1.36.1"
|
|
650
650
|
},
|
|
651
651
|
"peerDependenciesMeta": {
|
|
652
652
|
"@number-flow/react": {
|