@hjmds/react 1.34.0 → 1.35.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/actions.d.ts +23 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +61 -6
- package/dist/actions.js.map +1 -1
- package/dist/advanced-display.d.ts +35 -2
- package/dist/advanced-display.d.ts.map +1 -1
- package/dist/advanced-display.js +28 -9
- package/dist/advanced-display.js.map +1 -1
- package/dist/anchor.d.ts +3 -1
- package/dist/anchor.d.ts.map +1 -1
- package/dist/anchor.js +5 -5
- package/dist/anchor.js.map +1 -1
- package/dist/auth-screen.d.ts.map +1 -1
- package/dist/auth-screen.js +5 -2
- package/dist/auth-screen.js.map +1 -1
- package/dist/avatar-blobatar-motion.d.ts.map +1 -1
- package/dist/avatar-blobatar-motion.js +2 -1
- package/dist/avatar-blobatar-motion.js.map +1 -1
- package/dist/avatar-blobatar.d.ts.map +1 -1
- package/dist/avatar-blobatar.js +2 -1
- package/dist/avatar-blobatar.js.map +1 -1
- package/dist/bottom-cta.d.ts +8 -1
- package/dist/bottom-cta.d.ts.map +1 -1
- package/dist/bottom-cta.js +6 -2
- package/dist/bottom-cta.js.map +1 -1
- package/dist/carousel-motion.d.ts.map +1 -1
- package/dist/carousel-motion.js +11 -2
- package/dist/carousel-motion.js.map +1 -1
- package/dist/carousel.d.ts +10 -0
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js +23 -7
- package/dist/carousel.js.map +1 -1
- package/dist/collapsible.d.ts +6 -0
- package/dist/collapsible.d.ts.map +1 -1
- package/dist/collapsible.js +22 -20
- package/dist/collapsible.js.map +1 -1
- package/dist/collection-editing.d.ts +3 -1
- package/dist/collection-editing.d.ts.map +1 -1
- package/dist/collection-editing.js +5 -5
- package/dist/collection-editing.js.map +1 -1
- package/dist/collection-rail.d.ts +4 -4
- package/dist/collection-rail.d.ts.map +1 -1
- package/dist/collection-rail.js.map +1 -1
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +4 -1
- package/dist/conversation-row.js.map +1 -1
- package/dist/data-table.d.ts +2 -0
- package/dist/data-table.d.ts.map +1 -1
- package/dist/data-table.js +2 -2
- package/dist/data-table.js.map +1 -1
- package/dist/display.d.ts +60 -5
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +32 -9
- package/dist/display.js.map +1 -1
- package/dist/evidence.d.ts +1 -1
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +2 -1
- package/dist/evidence.js.map +1 -1
- package/dist/feedback.d.ts +5 -0
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +7 -5
- package/dist/feedback.js.map +1 -1
- package/dist/floating-action-button.js +1 -1
- package/dist/floating-action-button.js.map +1 -1
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +4 -4
- package/dist/forms.js.map +1 -1
- package/dist/image-choice.js +3 -3
- package/dist/image-choice.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/initial-focus.d.ts +6 -0
- package/dist/internal/initial-focus.d.ts.map +1 -1
- package/dist/internal/initial-focus.js +6 -0
- package/dist/internal/initial-focus.js.map +1 -1
- package/dist/internal/pending-content.d.ts +19 -0
- package/dist/internal/pending-content.d.ts.map +1 -0
- package/dist/internal/pending-content.js +34 -0
- package/dist/internal/pending-content.js.map +1 -0
- package/dist/internal/screen-footer.d.ts +4 -2
- package/dist/internal/screen-footer.d.ts.map +1 -1
- package/dist/internal/screen-footer.js +2 -2
- package/dist/internal/screen-footer.js.map +1 -1
- package/dist/internal.d.ts +9 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +4 -0
- package/dist/internal.js.map +1 -1
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +58 -4
- package/dist/navigation.js.map +1 -1
- package/dist/number-field.d.ts.map +1 -1
- package/dist/number-field.js +4 -3
- package/dist/number-field.js.map +1 -1
- package/dist/overlays.d.ts +4 -0
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +46 -18
- package/dist/overlays.js.map +1 -1
- package/dist/public-exports.generated.d.ts +6 -0
- package/dist/public-exports.generated.d.ts.map +1 -1
- package/dist/public-exports.generated.js +18 -0
- package/dist/public-exports.generated.js.map +1 -1
- package/dist/screen-flows.d.ts +13 -5
- package/dist/screen-flows.d.ts.map +1 -1
- package/dist/screen-flows.js +25 -14
- package/dist/screen-flows.js.map +1 -1
- package/dist/screens.d.ts +18 -5
- package/dist/screens.d.ts.map +1 -1
- package/dist/screens.js +22 -11
- package/dist/screens.js.map +1 -1
- package/dist/selection.d.ts +22 -0
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +32 -9
- package/dist/selection.js.map +1 -1
- package/dist/shortcut-rail.d.ts +27 -0
- package/dist/shortcut-rail.d.ts.map +1 -0
- package/dist/shortcut-rail.js +37 -0
- package/dist/shortcut-rail.js.map +1 -0
- package/dist/steps.d.ts +5 -2
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +3 -3
- package/dist/steps.js.map +1 -1
- package/dist/styles.css +223 -48
- package/dist/styles.layered.css +223 -48
- package/dist/task-list.d.ts +3 -1
- package/dist/task-list.d.ts.map +1 -1
- package/dist/task-list.js +2 -2
- package/dist/task-list.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +1 -0
- package/dist/theme.js.map +1 -1
- package/dist/time-picker.d.ts +9 -0
- package/dist/time-picker.d.ts.map +1 -0
- package/dist/time-picker.js +74 -0
- package/dist/time-picker.js.map +1 -0
- package/dist/top-bar.d.ts +4 -0
- package/dist/top-bar.d.ts.map +1 -1
- package/dist/top-bar.js +2 -2
- package/dist/top-bar.js.map +1 -1
- package/package.json +26 -15
package/dist/collapsible.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../src/collapsible.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n collapsibleRecipe,\n validateCollapsibleOpenState,\n type CollapsibleOpenState,\n} from \"@hjmds/design-contracts/components/collapsible\";\nimport { forwardRef, useId, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { assignRef, classNames } from \"./internal.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type CollapsibleProps = CollapsibleOpenState &\n Readonly<{\n /** The control's label; it also tells the user what will appear. */\n trigger: ReactNode;\n children: ReactNode;\n disabled?: boolean;\n /** Inline tools stay expanded without a disclosure trigger. */\n presentation?: \"disclosure\" | \"inline\";\n /** Preserve local input state while hidden; hidden content stays inaccessible. */\n keepMounted?: boolean;\n /**\n * `none` leaves the open/closed mark to the trigger, which then places `CollapsibleMarker` itself — for triggers\n * whose label is not a single row, where the end-aligned mark floated alone (FolderPreview, 2026-10-17 review).\n */\n marker?: \"end\" | \"none\";\n className?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(function Collapsible(\n { trigger, children, disabled = false, presentation = \"disclosure\", keepMounted = false, marker = \"end\", className, layoutStyle, ...openState },\n forwardedRef,\n) {\n validateCollapsibleOpenState(openState as CollapsibleOpenState);\n const controlled = openState.open !== undefined;\n const [internalOpen, setInternalOpen] = useState(openState.defaultOpen ?? false);\n const open = presentation === \"inline\" || (openState.open ?? internalOpen);\n const host = useRef<HTMLDivElement>(null);\n const button = useRef<HTMLButtonElement>(null);\n const content = useRef<HTMLDivElement>(null);\n const focusedContent = useRef(false);\n const wasOpen = useRef(open);\n useLayoutEffect(() => {\n // A controlled close can remove or hide the currently focused input without\n // activating the trigger. Recover only that focus, never an outside control.\n const active = host.current?.ownerDocument.activeElement;\n if (wasOpen.current && !open && focusedContent.current &&\n (content.current?.contains(active ?? null) || active === host.current?.ownerDocument.body)) {\n (disabled ? host.current : button.current)?.focus();\n }\n if (!open) focusedContent.current = false;\n wasOpen.current = open;\n }, [open, disabled]);\n const id = `${useId().replaceAll(\":\", \"\")}-collapsible`;\n return (\n <div\n ref={node => { host.current = node; assignRef(forwardedRef, node); }}\n tabIndex={-1}\n className={classNames(\"hjm-collapsible\", className)}\n data-state={open ? \"open\" : \"closed\"}\n style={{ ...layoutStyle, \"--hjm-collapsible-gap\": `${collapsibleRecipe.gap}px` } as CSSProperties}\n >\n <button\n ref={button}\n hidden={presentation === \"inline\"}\n type=\"button\"\n className=\"hjm-collapsible__trigger\"\n aria-expanded={open}\n aria-controls={`${id}-content`}\n disabled={disabled}\n onClick={event => {\n if (disabled || presentation === \"inline\") return;\n // Safari does not focus buttons on pointer activation; keep the closing\n // disclosure as the keyboard origin before its focused content disappears.\n if (open) event.currentTarget.focus();\n const next = !open;\n if (!controlled) setInternalOpen(next);\n openState.onOpenChange?.(next);\n }}\n >\n {trigger}\n {marker === \"end\" ? <CollapsibleMarker open={open} /> : null}\n </button>\n {/* Optional persistence keeps theme changes and closing tools from erasing local\n drafts. The HTML hidden boundary removes closed content from focus and speech. */}\n {open || keepMounted ? (\n <div ref={content} onFocusCapture={() => { focusedContent.current = true; }} onBlurCapture={event => { if (event.relatedTarget instanceof Node && !event.currentTarget.contains(event.relatedTarget)) focusedContent.current = false; }} hidden={!open} id={`${id}-content`} role=\"region\" className=\"hjm-collapsible__content\">{children}</div>\n ) : null}\n </div>\n );\n});\n\n/** The decorative open/closed mark; the expanded state itself travels through the trigger's aria-expanded. */\nexport function CollapsibleMarker({ open }: Readonly<{ open: boolean }>) {\n // The shared chevron at glyph.sm: the text \"▸\" rendered about 8px and read as static text (2026-10-17 review).\n // `chevronEnd` is a logical icon, so Icon mirrors it in RTL.\n return <span aria-hidden=\"true\" className=\"hjm-collapsible__marker\" data-state={open ? \"open\" : \"closed\"}><Icon name={open ? \"chevronDown\" : \"chevronEnd\"} size=\"sm\" tone=\"secondary\" decorative /></span>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../src/collapsible.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n collapsibleRecipe,\n validateCollapsibleOpenState,\n type CollapsibleOpenState,\n} from \"@hjmds/design-contracts/components/collapsible\";\nimport { forwardRef, useId, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { assignRef, classNames } from \"./internal.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { Spinner } from \"./internal/spinner.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type CollapsibleProps = CollapsibleOpenState &\n Readonly<{\n /** The control's label; it also tells the user what will appear. */\n trigger: ReactNode;\n /** Accessible action name when the trigger is artwork or has a shorter visible label. */\n triggerLabel?: string;\n /** Static heading beside the disclosure action, outside the button's accessible name. */\n title?: ReactNode;\n /** While content is being prepared, replace the action with one labeled spinner. */\n pendingLabel?: string;\n children: ReactNode;\n disabled?: boolean;\n /** Inline tools stay expanded without a disclosure trigger. */\n presentation?: \"disclosure\" | \"inline\";\n /** Preserve local input state while hidden; hidden content stays inaccessible. */\n keepMounted?: boolean;\n /**\n * `none` leaves the open/closed mark to the trigger, which then places `CollapsibleMarker` itself — for triggers\n * whose label is not a single row, where the end-aligned mark floated alone (FolderPreview, 2026-10-17 review).\n */\n marker?: \"end\" | \"none\";\n className?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(function Collapsible(\n { trigger, triggerLabel, title, pendingLabel, children, disabled = false, presentation = \"disclosure\", keepMounted = false, marker = \"end\", className, layoutStyle, ...openState },\n forwardedRef,\n) {\n validateCollapsibleOpenState(openState as CollapsibleOpenState);\n const controlled = openState.open !== undefined;\n const [internalOpen, setInternalOpen] = useState(openState.defaultOpen ?? false);\n const open = presentation === \"inline\" || (openState.open ?? internalOpen);\n const host = useRef<HTMLDivElement>(null);\n const button = useRef<HTMLButtonElement>(null);\n const content = useRef<HTMLDivElement>(null);\n const focusedContent = useRef(false);\n const contentOpen = open && pendingLabel === undefined;\n const wasOpen = useRef(contentOpen);\n useLayoutEffect(() => {\n // A controlled close can remove or hide the currently focused input without\n // activating the trigger. Recover only that focus, never an outside control.\n const active = host.current?.ownerDocument.activeElement;\n if (wasOpen.current && !contentOpen && focusedContent.current &&\n (content.current?.contains(active ?? null) || active === host.current?.ownerDocument.body)) {\n (disabled || pendingLabel !== undefined ? host.current : button.current)?.focus();\n }\n if (!contentOpen) focusedContent.current = false;\n wasOpen.current = contentOpen;\n }, [contentOpen, disabled, pendingLabel]);\n const id = `${useId().replaceAll(\":\", \"\")}-collapsible`;\n return (\n <div\n ref={node => { host.current = node; assignRef(forwardedRef, node); }}\n tabIndex={-1}\n className={classNames(\"hjm-collapsible\", className)}\n data-state={open ? \"open\" : \"closed\"}\n aria-busy={pendingLabel === undefined ? undefined : true}\n style={{ ...layoutStyle, \"--hjm-collapsible-gap\": `${collapsibleRecipe.gap}px` } as CSSProperties}\n >\n <div className=\"hjm-collapsible__header\" data-titled={title == null ? undefined : true} hidden={presentation === \"inline\"}>\n {title == null ? null : <div className=\"hjm-collapsible__title\">{title}</div>}\n {pendingLabel === undefined ? <button\n ref={button}\n hidden={presentation === \"inline\"}\n type=\"button\"\n className=\"hjm-collapsible__trigger\"\n aria-label={triggerLabel}\n aria-expanded={open}\n aria-controls={`${id}-content`}\n disabled={disabled}\n onClick={event => {\n if (disabled || presentation === \"inline\") return;\n // Safari does not focus buttons on pointer activation; keep the closing\n // disclosure as the keyboard origin before its focused content disappears.\n if (open) event.currentTarget.focus();\n const next = !open;\n if (!controlled) setInternalOpen(next);\n openState.onOpenChange?.(next);\n }}\n >\n {trigger}\n {marker === \"end\" ? <CollapsibleMarker open={open} /> : null}\n </button> : <span className=\"hjm-collapsible__pending\"><Spinner label={pendingLabel} size=\"small\" /></span>}\n </div>\n {/* Optional persistence keeps theme changes and closing tools from erasing local\n drafts. The HTML hidden boundary removes closed content from focus and speech. */}\n {contentOpen || keepMounted ? (\n <div ref={content} onFocusCapture={() => { focusedContent.current = true; }} onBlurCapture={event => { if (event.relatedTarget instanceof Node && !event.currentTarget.contains(event.relatedTarget)) focusedContent.current = false; }} hidden={!contentOpen} id={`${id}-content`} role=\"region\" className=\"hjm-collapsible__content\">{children}</div>\n ) : null}\n </div>\n );\n});\n\n/** The decorative open/closed mark; the expanded state itself travels through the trigger's aria-expanded. */\nexport function CollapsibleMarker({ open }: Readonly<{ open: boolean }>) {\n // The shared chevron at glyph.sm: the text \"▸\" rendered about 8px and read as static text (2026-10-17 review).\n // `chevronEnd` is a logical icon, so Icon mirrors it in RTL.\n return <span aria-hidden=\"true\" className=\"hjm-collapsible__marker\" data-state={open ? \"open\" : \"closed\"}><Icon name={open ? \"chevronDown\" : \"chevronEnd\"} size=\"sm\" tone=\"secondary\" decorative /></span>;\n}\n"]}
|
|
@@ -23,11 +23,13 @@ export type RepeatableFieldGroupProps = Omit<FieldGroupProps, "renderField"> & R
|
|
|
23
23
|
removeLabel: (id: string) => string;
|
|
24
24
|
minFields?: number;
|
|
25
25
|
maxFields?: number;
|
|
26
|
+
/** A referenced row may stay editable while removal is unavailable (Utilverse expense participants). */
|
|
27
|
+
isRemoveDisabled?: (id: string) => boolean;
|
|
26
28
|
/** Return the new stable id to focus after the controlled descriptor includes it. */
|
|
27
29
|
onAdd: () => string | undefined;
|
|
28
30
|
onRemove: (id: string) => void;
|
|
29
31
|
}>;
|
|
30
|
-
export declare function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFields, maxFields, onAdd, onRemove, ...props }: RepeatableFieldGroupProps): import("react").JSX.Element;
|
|
32
|
+
export declare function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFields, maxFields, isRemoveDisabled, onAdd, onRemove, ...props }: RepeatableFieldGroupProps): import("react").JSX.Element;
|
|
31
33
|
export type SelectionActionBarProps = Readonly<{
|
|
32
34
|
selectedIds: readonly string[];
|
|
33
35
|
selectionLabel: (count: number) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-editing.d.ts","sourceRoot":"","sources":["../src/collection-editing.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5F,OAAO,EAA8H,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAM/Q,OAAO,EAAc,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAO5F,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IACxH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrE,kGAAkG;IAClG,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD,CAAC,CAAC;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BAA0D;AA2C3G,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC;IACtF,WAAW,EAAE,CAAC,OAAO,EAAE,iBAAiB,GAAG;QAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;KAAE,KAAK,SAAS,CAAC;IAC5G,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC9F,qFAAqF;IACrF,KAAK,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE,CAAC,CAAC;AACH,wBAAgB,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAa,EAAE,SAAoB,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,yBAAyB,+
|
|
1
|
+
{"version":3,"file":"collection-editing.d.ts","sourceRoot":"","sources":["../src/collection-editing.tsx"],"names":[],"mappings":"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"}
|
|
@@ -54,7 +54,7 @@ function InlineEditBody(props) {
|
|
|
54
54
|
}
|
|
55
55
|
} }), _jsxs(Stack, { axis: "inline", gap: "sm", wrap: true, children: [_jsx(Button, { tone: "ghost", disabled: action.pending, onClick: close, children: props.cancelLabel }), _jsx(Button, { loading: action.pending, disabled: props.disabled === true || !!error, onClick: () => void save(), children: props.saveLabel })] }), action.failed ? _jsx(ErrorMessage, { children: props.errorLabel }) : null] }) });
|
|
56
56
|
}
|
|
57
|
-
export function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFields = 0, maxFields = Infinity, onAdd, onRemove, ...props }) {
|
|
57
|
+
export function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFields = 0, maxFields = Infinity, isRemoveDisabled, onAdd, onRemove, ...props }) {
|
|
58
58
|
const targets = useRef(new Map()), add = useRef(null);
|
|
59
59
|
const focus = useRef(undefined);
|
|
60
60
|
useLayoutEffect(() => {
|
|
@@ -70,15 +70,15 @@ export function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFi
|
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
const fields = props.descriptor.fields;
|
|
73
|
-
const live = useRef(true), policy = useRef({ fields, minFields, maxFields, onAdd, onRemove, disabled: props.descriptor.disabled });
|
|
74
|
-
policy.current = { fields, minFields, maxFields, onAdd, onRemove, disabled: props.descriptor.disabled };
|
|
73
|
+
const live = useRef(true), policy = useRef({ fields, minFields, maxFields, isRemoveDisabled, onAdd, onRemove, disabled: props.descriptor.disabled });
|
|
74
|
+
policy.current = { fields, minFields, maxFields, isRemoveDisabled, onAdd, onRemove, disabled: props.descriptor.disabled };
|
|
75
75
|
useEffect(() => { live.current = true; return () => { live.current = false; }; }, []);
|
|
76
76
|
return _jsxs(Stack, { gap: collectionEditingRecipe.gap, children: [_jsx(FieldGroup, { ...props, renderField: binding => _jsxs(Stack, { axis: "inline", gap: "xs", align: "end", children: [_jsx("div", { style: { flex: 1, minInlineSize: 0 }, children: renderField({ ...binding, focusRef: target => { if (target)
|
|
77
77
|
targets.current.set(binding.id, target);
|
|
78
78
|
else
|
|
79
|
-
targets.current.delete(binding.id); } }) }), _jsx(IconButton, { label: removeLabel(binding.id), tone: "ghost", edge: "end", disabled: binding.controlProps.disabled || fields.length <= minFields, onClick: binding.guardChange(() => {
|
|
79
|
+
targets.current.delete(binding.id); } }) }), _jsx(IconButton, { label: removeLabel(binding.id), tone: "ghost", edge: "end", disabled: binding.controlProps.disabled || fields.length <= minFields || isRemoveDisabled?.(binding.id) === true, onClick: binding.guardChange(() => {
|
|
80
80
|
const current = policy.current;
|
|
81
|
-
if (!live.current || current.disabled || current.fields.length <= current.minFields)
|
|
81
|
+
if (!live.current || current.disabled || current.fields.length <= current.minFields || current.isRemoveDisabled?.(binding.id))
|
|
82
82
|
return;
|
|
83
83
|
focus.current = focusAfterRemoval(current.fields.map(field => field.id), binding.id, current.fields.filter(field => field.disabled).map(field => field.id)) ?? null;
|
|
84
84
|
current.onRemove(binding.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-editing.js","sourceRoot":"","sources":["../src/collection-editing.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAyF,MAAM,4CAA4C,CAAC;AAC/Q,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAgD,MAAM,kBAAkB,CAAC;AAG5F,SAAS,YAAY,CAAC,EAAE,QAAQ,EAA2B;IACzD,OAAO,cAAK,IAAI,EAAC,OAAO,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,QAAQ,YAAE,QAAQ,GAAQ,GAAM,CAAC;AAC9I,CAAC;AAQD,MAAM,UAAU,UAAU,CAAC,KAAsB,IAAI,OAAO,KAAC,cAAc,OAAoB,KAAK,IAAnB,KAAK,CAAC,EAAE,CAAe,CAAC,CAAC,CAAC;AAC3G,SAAS,cAAc,CAAC,KAAsB;IAC5C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzF,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,MAAM,CAAmB,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAoB,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC9H,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,OAAO;YAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;aAC/B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAAC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;YAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QAAC,CAAC;IAClF,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;QAC3E,UAAU,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO;QAC3G,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,KAAK,EAAE,CAAC;IAC3C,CAAC,CAAC;IACF,OAAO,cAAK,GAAG,EAAE,KAAK,EAAE,IAAI,EAAC,OAAO,gBAAa,KAAK,CAAC,KAAK,YAGzD,CAAC,OAAO,CAAC,CAAC,CAAC,MAAC,KAAK,IAAC,IAAI,EAAC,QAAQ,EAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,aACtD,MAAC,KAAK,IAAC,GAAG,EAAC,KAAK,EAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAE,KAAC,IAAI,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,OAAO,YAAE,KAAK,CAAC,KAAK,GAAQ,EAAA,KAAC,IAAI,IAAC,QAAQ,EAAC,QAAQ,YAAE,KAAK,CAAC,KAAK,GAAQ,IAAQ,EAC1K,KAAC,UAAU,IAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,GAAG,GAAa,IACjO;YACN,CAAC,CAAC,MAAC,KAAK,IAAC,GAAG,EAAE,uBAAuB,CAAC,SAAS,aAC7C,KAAC,SAAS,IAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,KAC9G,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,QAAQ,EAC3E,SAAS,EAAE,KAAK,CAAC,EAAE;4BACjB,oEAAoE;4BACpE,IAAI,KAAK,CAAC,WAAW,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,KAAK,GAAG;gCAAE,OAAO;4BACnE,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;gCAAC,KAAK,CAAC,cAAc,EAAE,CAAC;gCAAC,KAAK,IAAI,EAAE,CAAC;4BAAC,CAAC;4BACnE,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gCAAC,KAAK,CAAC,cAAc,EAAE,CAAC;gCAAC,KAAK,CAAC,eAAe,EAAE,CAAC;gCAAC,KAAK,EAAE,CAAC;4BAAC,CAAC;wBAC9G,CAAC,GAAI,EACP,MAAC,KAAK,IAAC,IAAI,EAAC,QAAQ,EAAC,GAAG,EAAC,IAAI,EAAC,IAAI,mBAAC,KAAC,MAAM,IAAC,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,YAAG,KAAK,CAAC,WAAW,GAAU,EAC5H,KAAC,MAAM,IAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,YAAG,KAAK,CAAC,SAAS,GAAU,IAAQ,EAC9I,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAC,YAAY,cAAE,KAAK,CAAC,UAAU,GAAgB,CAAC,CAAC,CAAC,IAAI,IACjE,GACN,CAAC;AACT,CAAC;AAQD,MAAM,UAAU,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA6B;IACpK,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,GAAG,EAAuB,CAAC,EAAE,GAAG,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAC9F,MAAM,KAAK,GAAG,MAAM,CAA4B,SAAS,CAAC,CAAC;IAC3D,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO;QACxC,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;QAAC,CAAC;aAC3E,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;QAAC,CAAC;IAC1H,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnI,MAAM,CAAC,OAAO,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACxG,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,OAAO,MAAC,KAAK,IAAC,GAAG,EAAE,uBAAuB,CAAC,GAAG,aAG5C,KAAC,UAAU,OAAK,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,MAAC,KAAK,IAAC,IAAI,EAAC,QAAQ,EAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,aACtF,cAAK,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,YAAG,WAAW,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI,MAAM;oCAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;;oCAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAO,EACrM,KAAC,UAAU,IAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE;gCAC3K,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;gCAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS;oCAAE,OAAO;gCAC5F,KAAK,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC;gCACpK,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;4BAC/B,CAAC,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,QAAQ,GAAG,GAAa,IACjC,GAAI,EACZ,KAAC,MAAM,IAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC,WAAW,EAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE;oBAC3H,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;oBAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS;wBAAE,OAAO;oBAC5F,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;oBAAC,IAAI,EAAE,KAAK,SAAS;wBAAE,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;gBACvE,CAAC,YAAG,QAAQ,GAAU,IAChB,CAAC;AACX,CAAC;AASD,MAAM,UAAU,kBAAkB,CAAC,KAA8B;IAC/D,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpD,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAAC,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACvE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACnG,OAAO,cAAK,IAAI,EAAC,OAAO,gBAAa,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,YAAE,MAAC,KAAK,IAAC,GAAG,EAAC,IAAI,aAClG,KAAC,IAAI,IAAC,IAAI,EAAC,QAAQ,YAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAQ,EAC3E,MAAC,KAAK,IAAC,IAAI,EAAC,QAAQ,EAAC,GAAG,EAAC,IAAI,EAAC,IAAI,mBAC/B,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAC,MAAM,IAAe,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE;gCAC3R,IAAI,KAAK,CAAC,QAAQ;oCAAE,OAAO;gCAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gCACnD,IAAI,KAAK,CAAC,MAAM;oCAAE,KAAK,MAAM,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;4BAC/F,CAAC,YAAG,IAAI,CAAC,KAAK,IAJ0B,IAAI,CAAC,EAAE,CAIvB,CAAC,EACzB,KAAC,MAAM,IAAC,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,YAAG,KAAK,CAAC,UAAU,GAAU,EACzJ,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE;gCACzK,IAAI,CAAC,KAAK,CAAC,QAAQ;oCAAE,KAAK,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAS,CAAC,MAAM,EAAE,CAAC,CAAC;4BAC/E,CAAC,YAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,GAAU,CAAC,CAAC,CAAC,IAAI,IACnC,EACP,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAC,YAAY,cAAE,KAAK,CAAC,UAAU,GAAgB,CAAC,CAAC,CAAC,IAAI,IACjE,GAAM,CAAC;AACjB,CAAC;AAOD,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjG,wFAAwF;IACxF,OAAO,cAAK,IAAI,EAAC,OAAO,gBAAa,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAE,MAAC,KAAK,IAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,aAClK,KAAC,IAAI,IAAC,QAAQ,EAAC,QAAQ,YAAE,KAAK,CAAC,KAAK,GAAQ,EAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,YAAE,KAAK,CAAC,WAAW,GAAQ,CAAC,CAAC,CAAC,IAAI,EACpH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAC,MAAM,IAAiB,IAAI,EAAC,WAAW,EAAC,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC,EACxL,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ;wBAAE,KAAK,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,IAD7F,MAAM,CAAC,EAAE,CAC8F,CAAC,EAC3I,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAC,YAAY,cAAE,KAAK,CAAC,UAAU,GAAgB,CAAC,CAAC,CAAC,IAAI,IACjE,GAAM,CAAC;AACjB,CAAC;AAOD,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,IAAoC,EAAE,EAAE;QAClE,IAAI,KAAK,CAAC,QAAQ;YAAE,OAAO;QAC3B,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAAC,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO;YAAE,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACtH,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,KAAK,EAAE,EAAE,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;IAC5D,mHAAmH;IACnH,sHAAsH;IACtH,gHAAgH;IAChH,OAAO,MAAC,KAAK,IAAC,GAAG,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,qBAAkB,OAAO,aAAE,KAAC,IAAI,IAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAC,QAAQ,YAAE,KAAK,CAAC,KAAK,GAAQ,EACpH,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAC,KAAK,IAAiB,IAAI,EAAC,QAAQ,EAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,aACvF,KAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,GAAI,EACvR,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,QAAQ,IAAI,oBAAoB,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,WAAW,GAAG,GAAa,EAClP,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,EAAE,QAAQ,IAAI,oBAAoB,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,aAAa,GAAG,GAAa,KAHlN,MAAM,CAAC,EAAE,CAI1C,CAAC,IACH,CAAC;AACX,CAAC","sourcesContent":["\"use client\";\n\nimport { useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode } from \"react\";\nimport { useCompositionAction } from \"./internal/use-composition-action.js\";\nimport { assertDistinctIds, changeColumnSettings, collectionEditingRecipe, focusAfterRemoval, recoverableFilters, snapshotSelection, type ColumnSetting, type FilterRecoveryOption, type FocusTarget, type SelectionAction } from \"@hjmds/design-contracts/collection-editing\";\nimport { Button, IconButton } from \"./actions.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { TextField } from \"./forms.js\";\nimport { Checkbox } from \"./selection.js\";\nimport { Stack, Text } from \"./layout.js\";\nimport { FieldGroup, type FieldGroupBinding, type FieldGroupProps } from \"./field-group.js\";\n\n\nfunction ErrorMessage({ children }: { children: ReactNode }) {\n return <div role=\"alert\" style={{ display: \"grid\", placeItems: \"center\", textAlign: \"center\" }}><Text tone=\"danger\">{children}</Text></div>;\n}\n\nexport type InlineEditProps = Readonly<{\n id: string; value: string; label: string; editLabel: string; saveLabel: string; cancelLabel: string; errorLabel: string;\n disabled?: boolean; validate?: (draft: string) => string | undefined;\n /** Resolve only after confirming and updating the product value; reject to preserve the draft. */\n onSave: (draft: string) => void | Promise<void>;\n}>;\nexport function InlineEdit(props: InlineEditProps) { return <InlineEditBody key={props.id} {...props} />; }\nfunction InlineEditBody(props: InlineEditProps) {\n const [editing, setEditing] = useState(false), [draft, setDraft] = useState(props.value);\n const action = useCompositionAction(props.disabled);\n const input = useRef<HTMLInputElement>(null), trigger = useRef<HTMLButtonElement>(null), group = useRef<HTMLDivElement>(null);\n const restore = useRef(false);\n useLayoutEffect(() => {\n if (editing) input.current?.focus();\n else if (restore.current) { restore.current = false; trigger.current?.focus(); }\n }, [editing]);\n const error = props.validate?.(draft);\n const close = () => {\n restore.current = group.current?.contains(document.activeElement) ?? false;\n setEditing(false);\n };\n const save = async () => {\n if (props.disabled || error || action.pending || action.session.getSnapshot().status === \"pending\") return;\n const result = await action.run(\"save\", () => props.onSave(draft));\n if (result.status === \"success\") close();\n };\n return <div ref={group} role=\"group\" aria-label={props.label}>\n {/* Read state names the value with its label and edits through a pencil tool at the row end; a bare value beside a\n text \"Edit title\" button lost the label (2026-10-17 review). */}\n {!editing ? <Stack axis=\"inline\" gap=\"sm\" align=\"center\">\n <Stack gap=\"xxs\" layoutStyle={{ flex: 1, minInlineSize: 0 }}><Text variant=\"caption\" tone=\"muted\">{props.label}</Text><Text emphasis=\"strong\">{props.value}</Text></Stack>\n <IconButton ref={trigger} label={props.editLabel} tone=\"ghost\" edge=\"end\" disabled={props.disabled ?? false} onClick={() => { setDraft(props.value); action.session.reset(null); setEditing(true); }}><Icon name=\"edit\" /></IconButton>\n </Stack>\n : <Stack gap={collectionEditingRecipe.actionGap}>\n <TextField ref={input} label={props.label} value={draft} disabled={props.disabled ?? false} readOnly={action.pending}\n {...(error ? { error, \"aria-invalid\": true } : {})} onValueChange={setDraft}\n onKeyDown={event => {\n // Enter during IME composition confirms a character, not the title.\n if (event.nativeEvent.isComposing || event.keyCode === 229) return;\n if (event.key === \"Enter\") { event.preventDefault(); void save(); }\n if (event.key === \"Escape\" && !action.pending) { event.preventDefault(); event.stopPropagation(); close(); }\n }} />\n <Stack axis=\"inline\" gap=\"sm\" wrap><Button tone=\"ghost\" disabled={action.pending} onClick={close}>{props.cancelLabel}</Button>\n <Button loading={action.pending} disabled={props.disabled === true || !!error} onClick={() => void save()}>{props.saveLabel}</Button></Stack>\n {action.failed ? <ErrorMessage>{props.errorLabel}</ErrorMessage> : null}\n </Stack>}\n </div>;\n}\n\nexport type RepeatableFieldGroupProps = Omit<FieldGroupProps, \"renderField\"> & Readonly<{\n renderField: (binding: FieldGroupBinding & { focusRef: (target: FocusTarget | null) => void }) => ReactNode;\n addLabel: string; removeLabel: (id: string) => string; minFields?: number; maxFields?: number;\n /** Return the new stable id to focus after the controlled descriptor includes it. */\n onAdd: () => string | undefined; onRemove: (id: string) => void;\n}>;\nexport function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFields = 0, maxFields = Infinity, onAdd, onRemove, ...props }: RepeatableFieldGroupProps) {\n const targets = useRef(new Map<string, FocusTarget>()), add = useRef<HTMLButtonElement>(null);\n const focus = useRef<string | null | undefined>(undefined);\n useLayoutEffect(() => {\n if (focus.current === undefined) return;\n if (focus.current === null) { add.current?.focus(); focus.current = undefined; }\n else if (targets.current.has(focus.current)) { targets.current.get(focus.current)?.focus(); focus.current = undefined; }\n });\n const fields = props.descriptor.fields;\n const live = useRef(true), policy = useRef({ fields, minFields, maxFields, onAdd, onRemove, disabled: props.descriptor.disabled });\n policy.current = { fields, minFields, maxFields, onAdd, onRemove, disabled: props.descriptor.disabled };\n useEffect(() => { live.current = true; return () => { live.current = false; }; }, []);\n return <Stack gap={collectionEditingRecipe.gap}>\n {/* Remove is a row tool: a trash IconButton at the field's end whose label names the row (icon-button.md), not a\n full-width ghost text button under the field (2026-10-17 review). End-aligned so it sits beside the input. */}\n <FieldGroup {...props} renderField={binding => <Stack axis=\"inline\" gap=\"xs\" align=\"end\">\n <div style={{ flex: 1, minInlineSize: 0 }}>{renderField({ ...binding, focusRef: target => { if (target) targets.current.set(binding.id, target); else targets.current.delete(binding.id); } })}</div>\n <IconButton label={removeLabel(binding.id)} tone=\"ghost\" edge=\"end\" disabled={binding.controlProps.disabled || fields.length <= minFields} onClick={binding.guardChange(() => {\n const current = policy.current;\n if (!live.current || current.disabled || current.fields.length <= current.minFields) return;\n focus.current = focusAfterRemoval(current.fields.map(field => field.id), binding.id, current.fields.filter(field => field.disabled).map(field => field.id)) ?? null;\n current.onRemove(binding.id);\n })}><Icon name=\"delete\" /></IconButton>\n </Stack>} />\n <Button ref={add} tone=\"secondary\" disabled={props.descriptor.disabled === true || fields.length >= maxFields} onClick={() => {\n const current = policy.current;\n if (!live.current || current.disabled || current.fields.length >= current.maxFields) return;\n const id = current.onAdd(); if (id !== undefined) focus.current = id;\n }}>{addLabel}</Button>\n </Stack>;\n}\n\nexport type SelectionActionBarProps = Readonly<{\n selectedIds: readonly string[]; selectionLabel: (count: number) => string;\n clearLabel: string; onClear: () => void; actions: readonly SelectionAction[];\n onAction: (actionId: string, selectedIds: readonly string[]) => void | Promise<void>; errorLabel: string; disabled?: boolean;\n /** Product supplies the exact confirmed operation to undo; never restore an entire collection. */\n recovery?: Readonly<{ label: string; onUndo: () => void | Promise<void> }>;\n}>;\nexport function SelectionActionBar(props: SelectionActionBarProps) {\n const action = useCompositionAction(props.disabled);\n assertDistinctIds(props.actions); snapshotSelection(props.selectedIds);\n if (!props.selectedIds.length && !props.recovery && !action.pending && !action.failed) return null;\n return <div role=\"group\" aria-label={props.selectionLabel(props.selectedIds.length)}><Stack gap=\"sm\">\n <Text role=\"status\">{props.selectionLabel(props.selectedIds.length)}</Text>\n <Stack axis=\"inline\" gap=\"sm\" wrap>\n {props.actions.map(item => <Button key={item.id} tone={item.destructive ? \"danger\" : \"secondary\"} loading={action.active === `action:${item.id}`} disabled={props.disabled === true || (action.pending && action.active !== `action:${item.id}`) || !props.selectedIds.length} onClick={() => {\n if (props.disabled) return;\n const scope = snapshotSelection(props.selectedIds);\n if (scope.length) void action.run(`action:${item.id}`, () => props.onAction(item.id, scope));\n }}>{item.label}</Button>)}\n <Button tone=\"ghost\" disabled={props.disabled === true || action.pending || !props.selectedIds.length} onClick={props.onClear}>{props.clearLabel}</Button>\n {props.recovery ? <Button tone=\"ghost\" loading={action.active === \"undo\"} disabled={props.disabled === true || (action.pending && action.active !== \"undo\")} onClick={() => {\n if (!props.disabled) void action.run(\"undo\", () => props.recovery!.onUndo());\n }}>{props.recovery.label}</Button> : null}\n </Stack>\n {action.failed ? <ErrorMessage>{props.errorLabel}</ErrorMessage> : null}\n </Stack></div>;\n}\n\nexport type FilterRecoveryProps = Readonly<{\n title: string; description?: string; options: readonly FilterRecoveryOption[];\n optionLabel: (option: FilterRecoveryOption) => string; onApply: (id: string) => void | Promise<void>;\n errorLabel: string; disabled?: boolean;\n}>;\nexport function FilterRecovery(props: FilterRecoveryProps) {\n const action = useCompositionAction(props.disabled), options = recoverableFilters(props.options);\n // Fills the result area its host gives it (flex parent) and centers there, like Native.\n return <div role=\"group\" aria-label={props.title} style={{ display: \"grid\", placeItems: \"center\", flexGrow: 1, textAlign: \"center\" }}><Stack gap=\"sm\" align=\"center\">\n <Text emphasis=\"strong\">{props.title}</Text>{props.description ? <Text tone=\"muted\">{props.description}</Text> : null}\n {options.map(option => <Button key={option.id} tone=\"secondary\" loading={action.active === option.id} disabled={props.disabled === true || (action.pending && action.active !== option.id)}\n onClick={() => { if (!props.disabled) void action.run(option.id, () => props.onApply(option.id)); }}>{props.optionLabel(option)}</Button>)}\n {action.failed ? <ErrorMessage>{props.errorLabel}</ErrorMessage> : null}\n </Stack></div>;\n}\n\nexport type TableColumnSettingsProps = Readonly<{\n label: string; columns: readonly ColumnSetting[]; disabled?: boolean;\n earlierLabel: (column: ColumnSetting) => string; laterLabel: (column: ColumnSetting) => string;\n onColumnsChange: (columns: readonly ColumnSetting[]) => void;\n}>;\nexport function TableColumnSettings(props: TableColumnSettingsProps) {\n assertDistinctIds(props.columns);\n const change = (id: string, kind: \"toggle\" | \"earlier\" | \"later\") => {\n if (props.disabled) return;\n const next = changeColumnSettings(props.columns, id, kind); if (next !== props.columns) props.onColumnsChange(next);\n };\n const labelId = useId(), disabled = props.disabled === true;\n // One row per column: visibility checkbox, then reorder as icon tools (labels stay the accessible names); the last\n // tool takes edge=\"end\" so its glyph slot ends on the group's edge like the checkbox starts on it (2026-10-17 audit).\n // The group label is HJM Text like Native; a browser-default <legend> rendered differently (2026-10-17 review).\n return <Stack gap=\"sm\" role=\"group\" aria-labelledby={labelId}><Text id={labelId} emphasis=\"strong\">{props.label}</Text>\n {props.columns.map(column => <Stack key={column.id} axis=\"inline\" gap=\"xs\" align=\"center\">\n <Checkbox label={column.label} checked={column.visible} layoutStyle={{ flex: 1, minInlineSize: 0 }} disabled={disabled || column.locked === true || (column.visible && props.columns.filter(item => item.visible).length === 1)} onCheckedChange={() => change(column.id, \"toggle\")} />\n <IconButton label={props.earlierLabel(column)} tone=\"ghost\" disabled={disabled || changeColumnSettings(props.columns, column.id, \"earlier\") === props.columns} onClick={() => change(column.id, \"earlier\")}><Icon name=\"chevronUp\" /></IconButton>\n <IconButton label={props.laterLabel(column)} tone=\"ghost\" edge=\"end\" disabled={disabled || changeColumnSettings(props.columns, column.id, \"later\") === props.columns} onClick={() => change(column.id, \"later\")}><Icon name=\"chevronDown\" /></IconButton>\n </Stack>)}\n </Stack>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"collection-editing.js","sourceRoot":"","sources":["../src/collection-editing.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode } from \"react\";\nimport { useCompositionAction } from \"./internal/use-composition-action.js\";\nimport { assertDistinctIds, changeColumnSettings, collectionEditingRecipe, focusAfterRemoval, recoverableFilters, snapshotSelection, type ColumnSetting, type FilterRecoveryOption, type FocusTarget, type SelectionAction } from \"@hjmds/design-contracts/collection-editing\";\nimport { Button, IconButton } from \"./actions.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { TextField } from \"./forms.js\";\nimport { Checkbox } from \"./selection.js\";\nimport { Stack, Text } from \"./layout.js\";\nimport { FieldGroup, type FieldGroupBinding, type FieldGroupProps } from \"./field-group.js\";\n\n\nfunction ErrorMessage({ children }: { children: ReactNode }) {\n return <div role=\"alert\" style={{ display: \"grid\", placeItems: \"center\", textAlign: \"center\" }}><Text tone=\"danger\">{children}</Text></div>;\n}\n\nexport type InlineEditProps = Readonly<{\n id: string; value: string; label: string; editLabel: string; saveLabel: string; cancelLabel: string; errorLabel: string;\n disabled?: boolean; validate?: (draft: string) => string | undefined;\n /** Resolve only after confirming and updating the product value; reject to preserve the draft. */\n onSave: (draft: string) => void | Promise<void>;\n}>;\nexport function InlineEdit(props: InlineEditProps) { return <InlineEditBody key={props.id} {...props} />; }\nfunction InlineEditBody(props: InlineEditProps) {\n const [editing, setEditing] = useState(false), [draft, setDraft] = useState(props.value);\n const action = useCompositionAction(props.disabled);\n const input = useRef<HTMLInputElement>(null), trigger = useRef<HTMLButtonElement>(null), group = useRef<HTMLDivElement>(null);\n const restore = useRef(false);\n useLayoutEffect(() => {\n if (editing) input.current?.focus();\n else if (restore.current) { restore.current = false; trigger.current?.focus(); }\n }, [editing]);\n const error = props.validate?.(draft);\n const close = () => {\n restore.current = group.current?.contains(document.activeElement) ?? false;\n setEditing(false);\n };\n const save = async () => {\n if (props.disabled || error || action.pending || action.session.getSnapshot().status === \"pending\") return;\n const result = await action.run(\"save\", () => props.onSave(draft));\n if (result.status === \"success\") close();\n };\n return <div ref={group} role=\"group\" aria-label={props.label}>\n {/* Read state names the value with its label and edits through a pencil tool at the row end; a bare value beside a\n text \"Edit title\" button lost the label (2026-10-17 review). */}\n {!editing ? <Stack axis=\"inline\" gap=\"sm\" align=\"center\">\n <Stack gap=\"xxs\" layoutStyle={{ flex: 1, minInlineSize: 0 }}><Text variant=\"caption\" tone=\"muted\">{props.label}</Text><Text emphasis=\"strong\">{props.value}</Text></Stack>\n <IconButton ref={trigger} label={props.editLabel} tone=\"ghost\" edge=\"end\" disabled={props.disabled ?? false} onClick={() => { setDraft(props.value); action.session.reset(null); setEditing(true); }}><Icon name=\"edit\" /></IconButton>\n </Stack>\n : <Stack gap={collectionEditingRecipe.actionGap}>\n <TextField ref={input} label={props.label} value={draft} disabled={props.disabled ?? false} readOnly={action.pending}\n {...(error ? { error, \"aria-invalid\": true } : {})} onValueChange={setDraft}\n onKeyDown={event => {\n // Enter during IME composition confirms a character, not the title.\n if (event.nativeEvent.isComposing || event.keyCode === 229) return;\n if (event.key === \"Enter\") { event.preventDefault(); void save(); }\n if (event.key === \"Escape\" && !action.pending) { event.preventDefault(); event.stopPropagation(); close(); }\n }} />\n <Stack axis=\"inline\" gap=\"sm\" wrap><Button tone=\"ghost\" disabled={action.pending} onClick={close}>{props.cancelLabel}</Button>\n <Button loading={action.pending} disabled={props.disabled === true || !!error} onClick={() => void save()}>{props.saveLabel}</Button></Stack>\n {action.failed ? <ErrorMessage>{props.errorLabel}</ErrorMessage> : null}\n </Stack>}\n </div>;\n}\n\nexport type RepeatableFieldGroupProps = Omit<FieldGroupProps, \"renderField\"> & Readonly<{\n renderField: (binding: FieldGroupBinding & { focusRef: (target: FocusTarget | null) => void }) => ReactNode;\n addLabel: string; removeLabel: (id: string) => string; minFields?: number; maxFields?: number;\n /** A referenced row may stay editable while removal is unavailable (Utilverse expense participants). */\n isRemoveDisabled?: (id: string) => boolean;\n /** Return the new stable id to focus after the controlled descriptor includes it. */\n onAdd: () => string | undefined; onRemove: (id: string) => void;\n}>;\nexport function RepeatableFieldGroup({ renderField, addLabel, removeLabel, minFields = 0, maxFields = Infinity, isRemoveDisabled, onAdd, onRemove, ...props }: RepeatableFieldGroupProps) {\n const targets = useRef(new Map<string, FocusTarget>()), add = useRef<HTMLButtonElement>(null);\n const focus = useRef<string | null | undefined>(undefined);\n useLayoutEffect(() => {\n if (focus.current === undefined) return;\n if (focus.current === null) { add.current?.focus(); focus.current = undefined; }\n else if (targets.current.has(focus.current)) { targets.current.get(focus.current)?.focus(); focus.current = undefined; }\n });\n const fields = props.descriptor.fields;\n const live = useRef(true), policy = useRef({ fields, minFields, maxFields, isRemoveDisabled, onAdd, onRemove, disabled: props.descriptor.disabled });\n policy.current = { fields, minFields, maxFields, isRemoveDisabled, onAdd, onRemove, disabled: props.descriptor.disabled };\n useEffect(() => { live.current = true; return () => { live.current = false; }; }, []);\n return <Stack gap={collectionEditingRecipe.gap}>\n {/* Remove is a row tool: a trash IconButton at the field's end whose label names the row (icon-button.md), not a\n full-width ghost text button under the field (2026-10-17 review). End-aligned so it sits beside the input. */}\n <FieldGroup {...props} renderField={binding => <Stack axis=\"inline\" gap=\"xs\" align=\"end\">\n <div style={{ flex: 1, minInlineSize: 0 }}>{renderField({ ...binding, focusRef: target => { if (target) targets.current.set(binding.id, target); else targets.current.delete(binding.id); } })}</div>\n <IconButton label={removeLabel(binding.id)} tone=\"ghost\" edge=\"end\" disabled={binding.controlProps.disabled || fields.length <= minFields || isRemoveDisabled?.(binding.id) === true} onClick={binding.guardChange(() => {\n const current = policy.current;\n if (!live.current || current.disabled || current.fields.length <= current.minFields || current.isRemoveDisabled?.(binding.id)) return;\n focus.current = focusAfterRemoval(current.fields.map(field => field.id), binding.id, current.fields.filter(field => field.disabled).map(field => field.id)) ?? null;\n current.onRemove(binding.id);\n })}><Icon name=\"delete\" /></IconButton>\n </Stack>} />\n <Button ref={add} tone=\"secondary\" disabled={props.descriptor.disabled === true || fields.length >= maxFields} onClick={() => {\n const current = policy.current;\n if (!live.current || current.disabled || current.fields.length >= current.maxFields) return;\n const id = current.onAdd(); if (id !== undefined) focus.current = id;\n }}>{addLabel}</Button>\n </Stack>;\n}\n\nexport type SelectionActionBarProps = Readonly<{\n selectedIds: readonly string[]; selectionLabel: (count: number) => string;\n clearLabel: string; onClear: () => void; actions: readonly SelectionAction[];\n onAction: (actionId: string, selectedIds: readonly string[]) => void | Promise<void>; errorLabel: string; disabled?: boolean;\n /** Product supplies the exact confirmed operation to undo; never restore an entire collection. */\n recovery?: Readonly<{ label: string; onUndo: () => void | Promise<void> }>;\n}>;\nexport function SelectionActionBar(props: SelectionActionBarProps) {\n const action = useCompositionAction(props.disabled);\n assertDistinctIds(props.actions); snapshotSelection(props.selectedIds);\n if (!props.selectedIds.length && !props.recovery && !action.pending && !action.failed) return null;\n return <div role=\"group\" aria-label={props.selectionLabel(props.selectedIds.length)}><Stack gap=\"sm\">\n <Text role=\"status\">{props.selectionLabel(props.selectedIds.length)}</Text>\n <Stack axis=\"inline\" gap=\"sm\" wrap>\n {props.actions.map(item => <Button key={item.id} tone={item.destructive ? \"danger\" : \"secondary\"} loading={action.active === `action:${item.id}`} disabled={props.disabled === true || (action.pending && action.active !== `action:${item.id}`) || !props.selectedIds.length} onClick={() => {\n if (props.disabled) return;\n const scope = snapshotSelection(props.selectedIds);\n if (scope.length) void action.run(`action:${item.id}`, () => props.onAction(item.id, scope));\n }}>{item.label}</Button>)}\n <Button tone=\"ghost\" disabled={props.disabled === true || action.pending || !props.selectedIds.length} onClick={props.onClear}>{props.clearLabel}</Button>\n {props.recovery ? <Button tone=\"ghost\" loading={action.active === \"undo\"} disabled={props.disabled === true || (action.pending && action.active !== \"undo\")} onClick={() => {\n if (!props.disabled) void action.run(\"undo\", () => props.recovery!.onUndo());\n }}>{props.recovery.label}</Button> : null}\n </Stack>\n {action.failed ? <ErrorMessage>{props.errorLabel}</ErrorMessage> : null}\n </Stack></div>;\n}\n\nexport type FilterRecoveryProps = Readonly<{\n title: string; description?: string; options: readonly FilterRecoveryOption[];\n optionLabel: (option: FilterRecoveryOption) => string; onApply: (id: string) => void | Promise<void>;\n errorLabel: string; disabled?: boolean;\n}>;\nexport function FilterRecovery(props: FilterRecoveryProps) {\n const action = useCompositionAction(props.disabled), options = recoverableFilters(props.options);\n // Fills the result area its host gives it (flex parent) and centers there, like Native.\n return <div role=\"group\" aria-label={props.title} style={{ display: \"grid\", placeItems: \"center\", flexGrow: 1, textAlign: \"center\" }}><Stack gap=\"sm\" align=\"center\">\n <Text emphasis=\"strong\">{props.title}</Text>{props.description ? <Text tone=\"muted\">{props.description}</Text> : null}\n {options.map(option => <Button key={option.id} tone=\"secondary\" loading={action.active === option.id} disabled={props.disabled === true || (action.pending && action.active !== option.id)}\n onClick={() => { if (!props.disabled) void action.run(option.id, () => props.onApply(option.id)); }}>{props.optionLabel(option)}</Button>)}\n {action.failed ? <ErrorMessage>{props.errorLabel}</ErrorMessage> : null}\n </Stack></div>;\n}\n\nexport type TableColumnSettingsProps = Readonly<{\n label: string; columns: readonly ColumnSetting[]; disabled?: boolean;\n earlierLabel: (column: ColumnSetting) => string; laterLabel: (column: ColumnSetting) => string;\n onColumnsChange: (columns: readonly ColumnSetting[]) => void;\n}>;\nexport function TableColumnSettings(props: TableColumnSettingsProps) {\n assertDistinctIds(props.columns);\n const change = (id: string, kind: \"toggle\" | \"earlier\" | \"later\") => {\n if (props.disabled) return;\n const next = changeColumnSettings(props.columns, id, kind); if (next !== props.columns) props.onColumnsChange(next);\n };\n const labelId = useId(), disabled = props.disabled === true;\n // One row per column: visibility checkbox, then reorder as icon tools (labels stay the accessible names); the last\n // tool takes edge=\"end\" so its glyph slot ends on the group's edge like the checkbox starts on it (2026-10-17 audit).\n // The group label is HJM Text like Native; a browser-default <legend> rendered differently (2026-10-17 review).\n return <Stack gap=\"sm\" role=\"group\" aria-labelledby={labelId}><Text id={labelId} emphasis=\"strong\">{props.label}</Text>\n {props.columns.map(column => <Stack key={column.id} axis=\"inline\" gap=\"xs\" align=\"center\">\n <Checkbox label={column.label} checked={column.visible} layoutStyle={{ flex: 1, minInlineSize: 0 }} disabled={disabled || column.locked === true || (column.visible && props.columns.filter(item => item.visible).length === 1)} onCheckedChange={() => change(column.id, \"toggle\")} />\n <IconButton label={props.earlierLabel(column)} tone=\"ghost\" disabled={disabled || changeColumnSettings(props.columns, column.id, \"earlier\") === props.columns} onClick={() => change(column.id, \"earlier\")}><Icon name=\"chevronUp\" /></IconButton>\n <IconButton label={props.laterLabel(column)} tone=\"ghost\" edge=\"end\" disabled={disabled || changeColumnSettings(props.columns, column.id, \"later\") === props.columns} onClick={() => change(column.id, \"later\")}><Icon name=\"chevronDown\" /></IconButton>\n </Stack>)}\n </Stack>;\n}\n"]}
|
|
@@ -6,10 +6,10 @@ export type CollectionRailLabels = Readonly<{
|
|
|
6
6
|
next: string;
|
|
7
7
|
navigation: string;
|
|
8
8
|
}>;
|
|
9
|
-
export type CollectionRailProps = Omit<HTMLAttributes<HTMLDivElement>, "children"> & Readonly<{
|
|
9
|
+
export type CollectionRailProps<Item extends CollectionRailItem = CollectionRailItem> = Omit<HTMLAttributes<HTMLDivElement>, "children"> & Readonly<{
|
|
10
10
|
label: string;
|
|
11
|
-
items: readonly
|
|
12
|
-
renderItem: (item:
|
|
11
|
+
items: readonly Item[];
|
|
12
|
+
renderItem: (item: Item) => ReactNode;
|
|
13
13
|
labels: CollectionRailLabels;
|
|
14
14
|
density?: CollectionRailDensity;
|
|
15
15
|
emptyContent?: ReactNode;
|
|
@@ -26,5 +26,5 @@ export type CollectionRailProps = Omit<HTMLAttributes<HTMLDivElement>, "children
|
|
|
26
26
|
layoutStyle?: HjmCompositionStyleProp;
|
|
27
27
|
}>;
|
|
28
28
|
/** Finite all-mounted list placement; Card, inputs and Dialog keep their own state. */
|
|
29
|
-
export declare function CollectionRail({ label, items, renderItem, labels, density, emptyContent, defaultStartKey, onStartKeyChange, bleed, layoutStyle, ...props }: CollectionRailProps): import("react").JSX.Element;
|
|
29
|
+
export declare function CollectionRail<Item extends CollectionRailItem = CollectionRailItem>({ label, items, renderItem, labels, density, emptyContent, defaultStartKey, onStartKeyChange, bleed, layoutStyle, ...props }: CollectionRailProps<Item>): import("react").JSX.Element;
|
|
30
30
|
//# sourceMappingURL=collection-rail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-rail.d.ts","sourceRoot":"","sources":["../src/collection-rail.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/F,OAAO,EAG4B,KAAK,kBAAkB,EAAE,KAAK,qBAAqB,EACrF,MAAM,yCAAyC,CAAC;AAIjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACpG,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"collection-rail.d.ts","sourceRoot":"","sources":["../src/collection-rail.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/F,OAAO,EAG4B,KAAK,kBAAkB,EAAE,KAAK,qBAAqB,EACrF,MAAM,yCAAyC,CAAC;AAIjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACpG,MAAM,MAAM,mBAAmB,CAAC,IAAI,SAAS,kBAAkB,GAAG,kBAAkB,IAAI,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC;IAClJ,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAAC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC;IAC7E,MAAM,EAAE,oBAAoB,CAAC;IAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IACxF,6FAA6F;IAC7F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEH,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,IAAI,SAAS,kBAAkB,GAAG,kBAAkB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAA+C,EACtK,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,KAAa,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,CAAC,IAAI,CAAC,+BA8HnH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-rail.js","sourceRoot":"","sources":["../src/collection-rail.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useLayoutEffect, useRef, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport {\n collectionRailRecipe, validateCollectionRail, resolveCollectionRailLayout, resolveCollectionRailViewport,\n getCollectionRailTargetOffset, getCollectionRailItemOffset, getCollectionRailRevealOffset,\n getCollectionRailKeyboardIntent, type CollectionRailItem, type CollectionRailDensity, type CollectionRailLayout,\n} from \"@hjmds/design-contracts/collection-rail\";\nimport { IconButton } from \"./actions.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type CollectionRailLabels = Readonly<{ previous: string; next: string; navigation: string }>;\nexport type CollectionRailProps = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> & Readonly<{\n label: string; items: readonly CollectionRailItem[]; renderItem: (item: CollectionRailItem) => ReactNode;\n labels: CollectionRailLabels; density?: CollectionRailDensity; emptyContent?: ReactNode;\n /** Initial scroll anchor, not selection. Later collection changes reconcile by stable ID. */\n defaultStartKey?: string;\n /** Observed leading item, independent of product selection/detail state. Empty lists report null. */\n onStartKeyChange?: (key: string | null) => void;\n /**\n * Scroll to the screen edges from inside the default inset ScreenLayout body: the viewport reaches past the body\n * gutter (`--hjm-screen-body-inline`) and pads it back, so the first and last items rest on the gutter (no\n * `body-edge` + per-section gutter, spint home 2026-10-17). Place the rail directly in the body.\n */\n bleed?: boolean;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Finite all-mounted list placement; Card, inputs and Dialog keep their own state. */\nexport function CollectionRail({ label, items, renderItem, labels, density = collectionRailRecipe.defaults.density,\n emptyContent, defaultStartKey, onStartKeyChange, bleed = false, layoutStyle, ...props }: CollectionRailProps) {\n validateCollectionRail(items);\n if (!label.trim() || Object.values(labels).some(value => !value.trim())) throw new TypeError(\"CollectionRail labels must not be empty\");\n const theme = useOptionalHjmTheme(), direction = theme?.environment.direction ?? \"ltr\";\n const gap = collectionRailRecipe.gap;\n const viewportRef = useRef<HTMLDivElement>(null);\n const detachedFocus = useRef<HTMLElement | null>(null);\n useLayoutEffect(() => {\n const old = detachedFocus.current;\n detachedFocus.current = null;\n // A removed card must leave a keyboard origin in this collection, without\n // moving focus away from a surviving input or an external control.\n if (old && !old.isConnected && old.ownerDocument.activeElement === old.ownerDocument.body) {\n viewportRef.current?.focus({ preventScroll: true });\n }\n });\n const anchor = useRef<string | null>(defaultStartKey ?? items[0]?.id ?? null);\n const initialized = useRef(false);\n if (!initialized.current) { validateCollectionRail(items, defaultStartKey); initialized.current = true; }\n const callback = useRef(onStartKeyChange); callback.current = onStartKeyChange;\n const current = useRef({ layout: resolveCollectionRailLayout(items.length, 0, density, gap), offset: 0 });\n const pendingOffset = useRef<number | null>(null);\n const [position, setPosition] = useState(current.current);\n const identity = JSON.stringify(items.map(item => item.id));\n const itemsRef = useRef(items); itemsRef.current = items;\n\n function publish(layout: CollectionRailLayout, offset: number) {\n const resolved = resolveCollectionRailViewport(layout, offset);\n const key = itemsRef.current[resolved.startIndex]?.id ?? null;\n if (key !== anchor.current) { anchor.current = key; callback.current?.(key); }\n current.current = { layout, offset: resolved.offset };\n setPosition(current.current);\n }\n function scrollToOffset(offset: number, animated: boolean) {\n const viewport = viewportRef.current;\n if (!viewport) return;\n const resolved = resolveCollectionRailViewport(current.current.layout, offset);\n // CSS RTL scrollLeft is negative; clamp Safari rubber-banding through the\n // shared logical resolver rather than reversing data or selection keys.\n viewport.scrollTo({ left: direction === \"rtl\" ? -resolved.offset : resolved.offset,\n behavior: animated && !theme?.environment.reducedMotion ? \"smooth\" : \"instant\" });\n pendingOffset.current = animated && !theme?.environment.reducedMotion ? resolved.offset : null;\n // Smooth scroll is a request, not an observed viewport. Publishing its\n // destination now would disable the end action and report an unseen anchor.\n publish(current.current.layout, direction === \"rtl\" ? -viewport.scrollLeft : viewport.scrollLeft);\n }\n useLayoutEffect(() => {\n const viewport = viewportRef.current;\n if (!viewport) return;\n let initialMeasurement = true;\n function measure() {\n // clientWidth includes the bleed padding; item geometry uses the gutter-aligned box inside it.\n const style = getComputedStyle(viewport!);\n const room = (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);\n const next = resolveCollectionRailLayout(itemsRef.current.length, Math.max(0, viewport!.clientWidth - room), density, gap);\n // ResizeObserver also delivers an initial unchanged box. Re-aligning then\n // would undo a focus reveal that happened after the layout effect.\n if (!initialMeasurement && next.viewport === current.current.layout.viewport) return;\n initialMeasurement = false;\n pendingOffset.current = null;\n const index = Math.max(0, itemsRef.current.findIndex(item => item.id === anchor.current));\n let offset = next.count ? getCollectionRailItemOffset(next, index) : 0;\n const focused = document.activeElement?.closest(\"[data-collection-rail-item]\");\n const focusedIndex = focused && viewport!.contains(focused)\n ? itemsRef.current.findIndex(item => item.id === focused.getAttribute(\"data-collection-rail-item\")) : -1;\n // A narrower viewport cannot keep a distant focused action and the old\n // leading item visible together; focus exposure takes priority over anchor alignment.\n if (focusedIndex >= 0) offset = getCollectionRailRevealOffset(next, offset, focusedIndex);\n current.current = { layout: next, offset };\n // Width/direction changes keep the leading item's identity, and never\n // key/remount its input or detail owner (docs/collection-rail.md).\n viewport!.scrollTo({ left: direction === \"rtl\" ? -offset : offset, behavior: \"instant\" });\n publish(next, offset);\n }\n measure();\n const observer = new ResizeObserver(measure); observer.observe(viewport);\n return () => observer.disconnect();\n }, [identity, density, gap, direction, bleed]);\n\n function navigate(intent: \"previous\" | \"next\" | \"first\" | \"last\") {\n scrollToOffset(getCollectionRailTargetOffset(current.current.layout, pendingOffset.current ?? current.current.offset, intent), true);\n }\n const resolved = resolveCollectionRailViewport(position.layout, position.offset);\n return <div {...props} style={{ ...props.style, ...layoutStyle, minWidth: 0 }}\n data-collection-rail data-start-key={items[resolved.startIndex]?.id} dir={direction}\n onKeyDown={event => {\n props.onKeyDown?.(event);\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n // Item widgets own arrows/Home/End. Rail navigation belongs only to its\n // viewport and explicit controls, not an input nested in a visible card.\n if (event.target !== viewportRef.current && !(event.target instanceof Element && event.target.closest(\"[data-collection-rail-controls]\"))) return;\n const intent = getCollectionRailKeyboardIntent(event.key, direction);\n if (intent) { event.preventDefault(); navigate(intent); }\n }}>\n <div ref={viewportRef} role=\"list\" aria-label={label} tabIndex={0} data-collection-rail-viewport data-bleed={bleed || undefined}\n className=\"hjm-collection-rail__viewport\"\n style={{ overflowX: \"auto\", overscrollBehaviorX: \"contain\", minWidth: 0 }}\n onPointerDown={() => { pendingOffset.current = null; }} onWheel={() => { pendingOffset.current = null; }}\n onScroll={event => {\n const offset = direction === \"rtl\" ? -event.currentTarget.scrollLeft : event.currentTarget.scrollLeft;\n if (pendingOffset.current !== null && Math.abs(offset - pendingOffset.current) <= 0.5) pendingOffset.current = null;\n publish(current.current.layout, offset);\n }}>\n <div style={{ display: \"flex\", gap, width: \"max-content\", minWidth: \"100%\", paddingBlock: \"var(--hjm-space-xs)\" }}>\n {items.map((item, index) => <div key={item.id} role=\"listitem\" data-collection-rail-item={item.id}\n ref={node => {\n if (!node) return;\n return () => {\n const active = node.ownerDocument.activeElement;\n if (active instanceof HTMLElement && node.contains(active)) detachedFocus.current = active;\n };\n }}\n style={{ flex: \"0 0 auto\", width: position.layout.itemWidth || \"auto\", minWidth: 0 }}\n onFocusCapture={() => scrollToOffset(getCollectionRailRevealOffset(current.current.layout, current.current.offset, index), false)}>\n {renderItem(item)}\n </div>)}\n </div>\n {items.length === 0 ? emptyContent : null}\n </div>\n <div data-collection-rail-controls role=\"group\" aria-label={labels.navigation}\n style={{ display: \"flex\", flexWrap: \"wrap\", justifyContent: \"flex-end\", gap: \"var(--hjm-space-sm)\", marginBlockStart: \"var(--hjm-space-sm)\" }}>\n {/* Tool actions: icon buttons named by the localized label, as Carousel (2026-10-17 review E9). */}\n <IconButton label={labels.previous} tone=\"ghost\" aria-disabled={resolved.atStart} onClick={() => navigate(\"previous\")}><Icon name=\"chevronStart\" /></IconButton>\n <IconButton label={labels.next} tone=\"ghost\" aria-disabled={resolved.atEnd} onClick={() => navigate(\"next\")}><Icon name=\"chevronEnd\" /></IconButton>\n </div>\n </div>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"collection-rail.js","sourceRoot":"","sources":["../src/collection-rail.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useLayoutEffect, useRef, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport {\n collectionRailRecipe, validateCollectionRail, resolveCollectionRailLayout, resolveCollectionRailViewport,\n getCollectionRailTargetOffset, getCollectionRailItemOffset, getCollectionRailRevealOffset,\n getCollectionRailKeyboardIntent, type CollectionRailItem, type CollectionRailDensity, type CollectionRailLayout,\n} from \"@hjmds/design-contracts/collection-rail\";\nimport { IconButton } from \"./actions.js\";\nimport { Icon } from \"./supplemental-display.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type CollectionRailLabels = Readonly<{ previous: string; next: string; navigation: string }>;\nexport type CollectionRailProps<Item extends CollectionRailItem = CollectionRailItem> = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> & Readonly<{\n label: string; items: readonly Item[]; renderItem: (item: Item) => ReactNode;\n labels: CollectionRailLabels; density?: CollectionRailDensity; emptyContent?: ReactNode;\n /** Initial scroll anchor, not selection. Later collection changes reconcile by stable ID. */\n defaultStartKey?: string;\n /** Observed leading item, independent of product selection/detail state. Empty lists report null. */\n onStartKeyChange?: (key: string | null) => void;\n /**\n * Scroll to the screen edges from inside the default inset ScreenLayout body: the viewport reaches past the body\n * gutter (`--hjm-screen-body-inline`) and pads it back, so the first and last items rest on the gutter (no\n * `body-edge` + per-section gutter, spint home 2026-10-17). Place the rail directly in the body.\n */\n bleed?: boolean;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Finite all-mounted list placement; Card, inputs and Dialog keep their own state. */\nexport function CollectionRail<Item extends CollectionRailItem = CollectionRailItem>({ label, items, renderItem, labels, density = collectionRailRecipe.defaults.density,\n emptyContent, defaultStartKey, onStartKeyChange, bleed = false, layoutStyle, ...props }: CollectionRailProps<Item>) {\n validateCollectionRail(items);\n if (!label.trim() || Object.values(labels).some(value => !value.trim())) throw new TypeError(\"CollectionRail labels must not be empty\");\n const theme = useOptionalHjmTheme(), direction = theme?.environment.direction ?? \"ltr\";\n const gap = collectionRailRecipe.gap;\n const viewportRef = useRef<HTMLDivElement>(null);\n const detachedFocus = useRef<HTMLElement | null>(null);\n useLayoutEffect(() => {\n const old = detachedFocus.current;\n detachedFocus.current = null;\n // A removed card must leave a keyboard origin in this collection, without\n // moving focus away from a surviving input or an external control.\n if (old && !old.isConnected && old.ownerDocument.activeElement === old.ownerDocument.body) {\n viewportRef.current?.focus({ preventScroll: true });\n }\n });\n const anchor = useRef<string | null>(defaultStartKey ?? items[0]?.id ?? null);\n const initialized = useRef(false);\n if (!initialized.current) { validateCollectionRail(items, defaultStartKey); initialized.current = true; }\n const callback = useRef(onStartKeyChange); callback.current = onStartKeyChange;\n const current = useRef({ layout: resolveCollectionRailLayout(items.length, 0, density, gap), offset: 0 });\n const pendingOffset = useRef<number | null>(null);\n const [position, setPosition] = useState(current.current);\n const identity = JSON.stringify(items.map(item => item.id));\n const itemsRef = useRef(items); itemsRef.current = items;\n\n function publish(layout: CollectionRailLayout, offset: number) {\n const resolved = resolveCollectionRailViewport(layout, offset);\n const key = itemsRef.current[resolved.startIndex]?.id ?? null;\n if (key !== anchor.current) { anchor.current = key; callback.current?.(key); }\n current.current = { layout, offset: resolved.offset };\n setPosition(current.current);\n }\n function scrollToOffset(offset: number, animated: boolean) {\n const viewport = viewportRef.current;\n if (!viewport) return;\n const resolved = resolveCollectionRailViewport(current.current.layout, offset);\n // CSS RTL scrollLeft is negative; clamp Safari rubber-banding through the\n // shared logical resolver rather than reversing data or selection keys.\n viewport.scrollTo({ left: direction === \"rtl\" ? -resolved.offset : resolved.offset,\n behavior: animated && !theme?.environment.reducedMotion ? \"smooth\" : \"instant\" });\n pendingOffset.current = animated && !theme?.environment.reducedMotion ? resolved.offset : null;\n // Smooth scroll is a request, not an observed viewport. Publishing its\n // destination now would disable the end action and report an unseen anchor.\n publish(current.current.layout, direction === \"rtl\" ? -viewport.scrollLeft : viewport.scrollLeft);\n }\n useLayoutEffect(() => {\n const viewport = viewportRef.current;\n if (!viewport) return;\n let initialMeasurement = true;\n function measure() {\n // clientWidth includes the bleed padding; item geometry uses the gutter-aligned box inside it.\n const style = getComputedStyle(viewport!);\n const room = (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);\n const next = resolveCollectionRailLayout(itemsRef.current.length, Math.max(0, viewport!.clientWidth - room), density, gap);\n // ResizeObserver also delivers an initial unchanged box. Re-aligning then\n // would undo a focus reveal that happened after the layout effect.\n if (!initialMeasurement && next.viewport === current.current.layout.viewport) return;\n initialMeasurement = false;\n pendingOffset.current = null;\n const index = Math.max(0, itemsRef.current.findIndex(item => item.id === anchor.current));\n let offset = next.count ? getCollectionRailItemOffset(next, index) : 0;\n const focused = document.activeElement?.closest(\"[data-collection-rail-item]\");\n const focusedIndex = focused && viewport!.contains(focused)\n ? itemsRef.current.findIndex(item => item.id === focused.getAttribute(\"data-collection-rail-item\")) : -1;\n // A narrower viewport cannot keep a distant focused action and the old\n // leading item visible together; focus exposure takes priority over anchor alignment.\n if (focusedIndex >= 0) offset = getCollectionRailRevealOffset(next, offset, focusedIndex);\n current.current = { layout: next, offset };\n // Width/direction changes keep the leading item's identity, and never\n // key/remount its input or detail owner (docs/collection-rail.md).\n viewport!.scrollTo({ left: direction === \"rtl\" ? -offset : offset, behavior: \"instant\" });\n publish(next, offset);\n }\n measure();\n const observer = new ResizeObserver(measure); observer.observe(viewport);\n return () => observer.disconnect();\n }, [identity, density, gap, direction, bleed]);\n\n function navigate(intent: \"previous\" | \"next\" | \"first\" | \"last\") {\n scrollToOffset(getCollectionRailTargetOffset(current.current.layout, pendingOffset.current ?? current.current.offset, intent), true);\n }\n const resolved = resolveCollectionRailViewport(position.layout, position.offset);\n return <div {...props} style={{ ...props.style, ...layoutStyle, minWidth: 0 }}\n data-collection-rail data-start-key={items[resolved.startIndex]?.id} dir={direction}\n onKeyDown={event => {\n props.onKeyDown?.(event);\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n // Item widgets own arrows/Home/End. Rail navigation belongs only to its\n // viewport and explicit controls, not an input nested in a visible card.\n if (event.target !== viewportRef.current && !(event.target instanceof Element && event.target.closest(\"[data-collection-rail-controls]\"))) return;\n const intent = getCollectionRailKeyboardIntent(event.key, direction);\n if (intent) { event.preventDefault(); navigate(intent); }\n }}>\n <div ref={viewportRef} role=\"list\" aria-label={label} tabIndex={0} data-collection-rail-viewport data-bleed={bleed || undefined}\n className=\"hjm-collection-rail__viewport\"\n style={{ overflowX: \"auto\", overscrollBehaviorX: \"contain\", minWidth: 0 }}\n onPointerDown={() => { pendingOffset.current = null; }} onWheel={() => { pendingOffset.current = null; }}\n onScroll={event => {\n const offset = direction === \"rtl\" ? -event.currentTarget.scrollLeft : event.currentTarget.scrollLeft;\n if (pendingOffset.current !== null && Math.abs(offset - pendingOffset.current) <= 0.5) pendingOffset.current = null;\n publish(current.current.layout, offset);\n }}>\n <div style={{ display: \"flex\", gap, width: \"max-content\", minWidth: \"100%\", paddingBlock: \"var(--hjm-space-xs)\" }}>\n {items.map((item, index) => <div key={item.id} role=\"listitem\" data-collection-rail-item={item.id}\n ref={node => {\n if (!node) return;\n return () => {\n const active = node.ownerDocument.activeElement;\n if (active instanceof HTMLElement && node.contains(active)) detachedFocus.current = active;\n };\n }}\n style={{ flex: \"0 0 auto\", width: position.layout.itemWidth || \"auto\", minWidth: 0 }}\n onFocusCapture={() => scrollToOffset(getCollectionRailRevealOffset(current.current.layout, current.current.offset, index), false)}>\n {renderItem(item)}\n </div>)}\n </div>\n {items.length === 0 ? emptyContent : null}\n </div>\n <div data-collection-rail-controls role=\"group\" aria-label={labels.navigation}\n style={{ display: \"flex\", flexWrap: \"wrap\", justifyContent: \"flex-end\", gap: \"var(--hjm-space-sm)\", marginBlockStart: \"var(--hjm-space-sm)\" }}>\n {/* Tool actions: icon buttons named by the localized label, as Carousel (2026-10-17 review E9). */}\n <IconButton label={labels.previous} tone=\"ghost\" aria-disabled={resolved.atStart} onClick={() => navigate(\"previous\")}><Icon name=\"chevronStart\" /></IconButton>\n <IconButton label={labels.next} tone=\"ghost\" aria-disabled={resolved.atEnd} onClick={() => navigate(\"next\")}><Icon name=\"chevronEnd\" /></IconButton>\n </div>\n </div>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-row.d.ts","sourceRoot":"","sources":["../src/conversation-row.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CACvF,CAAC,CAAC;AAEH,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAc,EAAE,EAAE,oBAAoB,+
|
|
1
|
+
{"version":3,"file":"conversation-row.d.ts","sourceRoot":"","sources":["../src/conversation-row.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CACvF,CAAC,CAAC;AAEH,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAc,EAAE,EAAE,oBAAoB,+BAgBzG"}
|
package/dist/conversation-row.js
CHANGED
|
@@ -3,6 +3,9 @@ import { conversationRowRecipe as recipe } from "@hjmds/design-contracts/convers
|
|
|
3
3
|
import { Text } from "./layout.js";
|
|
4
4
|
/** Presentation inside a router-owned link: the host supplies its full accessible name. */
|
|
5
5
|
export function ConversationRow({ title, preview, metadata, avatar, unread = false }) {
|
|
6
|
-
|
|
6
|
+
// Separators join visible fields; a missing preview must not leave a leading dot.
|
|
7
|
+
const hasPreview = preview.trim().length > 0;
|
|
8
|
+
const hasMetadata = metadata.trim().length > 0;
|
|
9
|
+
return _jsxs("span", { "aria-hidden": "true", "data-hjm-conversation-row": "true", "data-unread": unread || undefined, style: { display: "flex", alignItems: "center", gap: recipe.gap, paddingInline: recipe.paddingInline, paddingBlock: recipe.paddingBlock, minWidth: 0, width: "100%", boxSizing: "border-box" }, children: [_jsx("span", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: recipe.avatarSize, height: recipe.avatarSize, flexShrink: 0, borderRadius: "50%", overflow: "hidden" }, children: avatar }), _jsxs("span", { style: { display: "flex", flexDirection: "column", gap: recipe.contentGap, flex: 1, minWidth: 0 }, children: [_jsx(Text, { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontWeight: unread ? recipe.unreadTitleWeight : recipe.titleWeight }, children: title }), _jsxs("span", { style: { display: "flex", minWidth: 0 }, children: [hasPreview ? _jsx(Text, { variant: "label", tone: unread ? "primary" : "subtle", style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontWeight: unread ? recipe.unreadPreviewWeight : recipe.titleWeight }, children: preview }) : null, hasMetadata ? _jsx(Text, { variant: "label", tone: unread ? "primary" : "subtle", style: { flexShrink: 0, /* "pre": flex items drop the leading space of " · " (2026-10-17 comparison); still no wrap. */ whiteSpace: "pre", fontWeight: unread ? recipe.unreadPreviewWeight : recipe.titleWeight }, children: hasPreview ? ` · ${metadata}` : metadata }) : null] })] }), unread ? _jsx("span", { "data-hjm-unread-dot": "true", style: { width: recipe.unreadSize, height: recipe.unreadSize, flexShrink: 0, borderRadius: "50%", background: "var(--hjm-color-content-brand)" } }) : null] });
|
|
7
10
|
}
|
|
8
11
|
//# sourceMappingURL=conversation-row.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-row.js","sourceRoot":"","sources":["../src/conversation-row.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,qBAAqB,IAAI,MAAM,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAMnC,2FAA2F;AAC3F,MAAM,UAAU,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAwB;IACxG,OAAO,+BAAkB,MAAM,+BAA2B,MAAM,iBAAc,MAAM,IAAI,SAAS,EAC/F,KAAK,EAAE,EAAC,OAAO,EAAC,MAAM,EAAC,UAAU,EAAC,QAAQ,EAAC,GAAG,EAAC,MAAM,CAAC,GAAG,EAAC,aAAa,EAAC,MAAM,CAAC,aAAa,EAAC,YAAY,EAAC,MAAM,CAAC,YAAY,EAAC,QAAQ,EAAC,CAAC,EAAC,KAAK,EAAC,MAAM,EAAC,SAAS,EAAC,YAAY,EAAC,aAC7K,eAAM,KAAK,EAAE,EAAC,OAAO,EAAC,MAAM,EAAC,UAAU,EAAC,QAAQ,EAAC,cAAc,EAAC,QAAQ,EAAC,KAAK,EAAC,MAAM,CAAC,UAAU,EAAC,MAAM,EAAC,MAAM,CAAC,UAAU,EAAC,UAAU,EAAC,CAAC,EAAC,YAAY,EAAC,KAAK,EAAC,QAAQ,EAAC,QAAQ,EAAC,YAAG,MAAM,GAAQ,EAC7L,gBAAM,KAAK,EAAE,EAAC,OAAO,EAAC,MAAM,EAAC,aAAa,EAAC,QAAQ,EAAC,GAAG,EAAC,MAAM,CAAC,UAAU,EAAC,IAAI,EAAC,CAAC,EAAC,QAAQ,EAAC,CAAC,EAAC,aAC1F,KAAC,IAAI,IAAC,KAAK,EAAE,EAAC,QAAQ,EAAC,QAAQ,EAAC,YAAY,EAAC,UAAU,EAAC,UAAU,EAAC,QAAQ,EAAC,UAAU,EAAC,MAAM,CAAA,CAAC,CAAA,MAAM,CAAC,iBAAiB,CAAA,CAAC,CAAA,MAAM,CAAC,WAAW,EAAC,YAAG,KAAK,GAAQ,EAC1J,gBAAM,KAAK,EAAE,EAAC,OAAO,EAAC,MAAM,EAAC,QAAQ,EAAC,CAAC,EAAC,
|
|
1
|
+
{"version":3,"file":"conversation-row.js","sourceRoot":"","sources":["../src/conversation-row.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from \"react\";\nimport { conversationRowRecipe as recipe } from \"@hjmds/design-contracts/conversation-row\";\nimport { Text } from \"./layout.js\";\n\nexport type ConversationRowProps = Readonly<{\n title: string; preview: string; metadata: string; avatar: ReactNode; unread?: boolean;\n}>;\n\n/** Presentation inside a router-owned link: the host supplies its full accessible name. */\nexport function ConversationRow({ title, preview, metadata, avatar, unread = false }: ConversationRowProps) {\n // Separators join visible fields; a missing preview must not leave a leading dot.\n const hasPreview = preview.trim().length > 0;\n const hasMetadata = metadata.trim().length > 0;\n return <span aria-hidden=\"true\" data-hjm-conversation-row=\"true\" data-unread={unread || undefined}\n style={{display:\"flex\",alignItems:\"center\",gap:recipe.gap,paddingInline:recipe.paddingInline,paddingBlock:recipe.paddingBlock,minWidth:0,width:\"100%\",boxSizing:\"border-box\"}}>\n <span style={{display:\"flex\",alignItems:\"center\",justifyContent:\"center\",width:recipe.avatarSize,height:recipe.avatarSize,flexShrink:0,borderRadius:\"50%\",overflow:\"hidden\"}}>{avatar}</span>\n <span style={{display:\"flex\",flexDirection:\"column\",gap:recipe.contentGap,flex:1,minWidth:0}}>\n <Text style={{overflow:\"hidden\",textOverflow:\"ellipsis\",whiteSpace:\"nowrap\",fontWeight:unread?recipe.unreadTitleWeight:recipe.titleWeight}}>{title}</Text>\n <span style={{display:\"flex\",minWidth:0}}>\n {hasPreview ? <Text variant=\"label\" tone={unread?\"primary\":\"subtle\"} style={{overflow:\"hidden\",textOverflow:\"ellipsis\",whiteSpace:\"nowrap\",fontWeight:unread?recipe.unreadPreviewWeight:recipe.titleWeight}}>{preview}</Text> : null}\n {hasMetadata ? <Text variant=\"label\" tone={unread?\"primary\":\"subtle\"} style={{flexShrink:0,/* \"pre\": flex items drop the leading space of \" · \" (2026-10-17 comparison); still no wrap. */whiteSpace:\"pre\",fontWeight:unread?recipe.unreadPreviewWeight:recipe.titleWeight}}>{hasPreview ? ` · ${metadata}` : metadata}</Text> : null}\n </span>\n </span>\n {unread?<span data-hjm-unread-dot=\"true\" style={{width:recipe.unreadSize,height:recipe.unreadSize,flexShrink:0,borderRadius:\"50%\",background:\"var(--hjm-color-content-brand)\"}}/>:null}\n </span>;\n}\n"]}
|
package/dist/data-table.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type DataTableProps<ColumnKey extends string = string, RowKey extends str
|
|
|
16
16
|
rows: readonly DataTableRowDescriptor<RowKey>[];
|
|
17
17
|
labels: DataTableLabels;
|
|
18
18
|
renderCell: (rowId: RowKey, columnId: ColumnKey) => ReactNode;
|
|
19
|
+
/** Text for rich cells. Native composes the row name; Web labels each cell. Omit to use visible primitive text. */
|
|
20
|
+
getCellText?: (rowId: RowKey, columnId: ColumnKey) => string | undefined;
|
|
19
21
|
selection?: DataTableSelection<RowKey>;
|
|
20
22
|
sortState?: DataTableSortState<ColumnKey>;
|
|
21
23
|
sortCycle?: DataTableSortCycle;
|
package/dist/data-table.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../src/data-table.tsx"],"names":[],"mappings":"AACA,OAAO,EAaL,KAAK,mBAAmB,EAExB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAA8E,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGnH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE5E,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,iFAAiF;IACjF,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC;CAC/E,CAAC,CAAC;AAEH,MAAM,MAAM,cAAc,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC;IACvG,OAAO,EAAE,SAAS,yBAAyB,CAAC,SAAS,CAAC,EAAE,CAAC;IACzD,IAAI,EAAE,SAAS,sBAAsB,CAAC,MAAM,CAAC,EAAE,CAAC;IAChD,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IAC9D,SAAS,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC1C,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;IAC7D,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,iFAAiF;IACjF,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IAChD,2DAA2D;IAC3D,YAAY,CAAC,EAAE,SAAS,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC;IAC1D,sFAAsF;IACtF,SAAS,CAAC,EAAE,SAAS,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;IACjD,kGAAkG;IAClG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,KAAK,QAAQ,CAAC;QAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IAC1I,6FAA6F;IAC7F,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAwCH,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../src/data-table.tsx"],"names":[],"mappings":"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"}
|
package/dist/data-table.js
CHANGED
|
@@ -38,7 +38,7 @@ function bodySections(items) {
|
|
|
38
38
|
// An empty table still renders one (empty) tbody, as before row groups existed.
|
|
39
39
|
return sections.length > 0 ? sections : [{ group: null, rows: [] }];
|
|
40
40
|
}
|
|
41
|
-
export const DataTable = forwardRef(function DataTable({ columns, rows, labels, renderCell, selection, sortState = null, sortCycle = dataTableDefaults.sortCycle, onSortChange, asyncState = { status: "idle" }, density: densityProp, footer, summaryRow, columnGroups, rowGroups, cellStyle, heatColors, maxBodyHeight, className, layoutStyle, }, forwardedRef) {
|
|
41
|
+
export const DataTable = forwardRef(function DataTable({ columns, rows, labels, renderCell, getCellText, selection, sortState = null, sortCycle = dataTableDefaults.sortCycle, onSortChange, asyncState = { status: "idle" }, density: densityProp, footer, summaryRow, columnGroups, rowGroups, cellStyle, heatColors, maxBodyHeight, className, layoutStyle, }, forwardedRef) {
|
|
42
42
|
// Unconditional: `??` on the hook call would break the rules of hooks.
|
|
43
43
|
const densityDefault = useHjmDensityDefault({ comfortable: "regular", compact: "compact" });
|
|
44
44
|
const density = densityProp ?? densityDefault;
|
|
@@ -158,7 +158,7 @@ export const DataTable = forwardRef(function DataTable({ columns, rows, labels,
|
|
|
158
158
|
const emphasis = tableCellEmphasis(cellStyle?.(row.id, column.id), heatColors);
|
|
159
159
|
// Sub-rows (TanStack `depth`) indent only the first column, which is the pinned one when pinning.
|
|
160
160
|
const depth = columnIndex === 0 ? row.depth ?? 0 : 0;
|
|
161
|
-
return (_jsx("td", { className: classNames(sticky.className, emphasis.heat && "hjm-table-family__heat"), "data-tone": emphasis.tone, "data-heat": emphasis.heat, "data-depth": depth > 0 ? depth : undefined, style: {
|
|
161
|
+
return (_jsx("td", { "aria-label": getCellText?.(row.id, column.id), className: classNames(sticky.className, emphasis.heat && "hjm-table-family__heat"), "data-tone": emphasis.tone, "data-heat": emphasis.heat, "data-depth": depth > 0 ? depth : undefined, style: {
|
|
162
162
|
textAlign: column.align ?? dataTableColumnDefaults.align,
|
|
163
163
|
...emphasis.style,
|
|
164
164
|
...(depth > 0 ? { "--hjm-data-table-indent": `${depth * dataTableFamilyRecipe.depthIndent}px` } : {}),
|