@molecule/app-ui-react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +115 -0
- package/README.md +2786 -0
- package/dist/components/Accordion.d.ts +12 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion.js +80 -0
- package/dist/components/Accordion.js.map +1 -0
- package/dist/components/Alert.d.ts +26 -0
- package/dist/components/Alert.d.ts.map +1 -0
- package/dist/components/Alert.js +53 -0
- package/dist/components/Alert.js.map +1 -0
- package/dist/components/AuthGuard.d.ts +66 -0
- package/dist/components/AuthGuard.d.ts.map +1 -0
- package/dist/components/AuthGuard.js +42 -0
- package/dist/components/AuthGuard.js.map +1 -0
- package/dist/components/Avatar.d.ts +12 -0
- package/dist/components/Avatar.d.ts.map +1 -0
- package/dist/components/Avatar.js +25 -0
- package/dist/components/Avatar.js.map +1 -0
- package/dist/components/Badge.d.ts +12 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Badge.js +18 -0
- package/dist/components/Badge.js.map +1 -0
- package/dist/components/Button.d.ts +12 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +19 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/Card.d.ts +34 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Card.js +71 -0
- package/dist/components/Card.js.map +1 -0
- package/dist/components/Checkbox.d.ts +12 -0
- package/dist/components/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox.js +41 -0
- package/dist/components/Checkbox.js.map +1 -0
- package/dist/components/Dropdown.d.ts +38 -0
- package/dist/components/Dropdown.d.ts.map +1 -0
- package/dist/components/Dropdown.js +352 -0
- package/dist/components/Dropdown.js.map +1 -0
- package/dist/components/EmptyState.d.ts +15 -0
- package/dist/components/EmptyState.d.ts.map +1 -0
- package/dist/components/EmptyState.js +20 -0
- package/dist/components/EmptyState.js.map +1 -0
- package/dist/components/FloatingInput.d.ts +22 -0
- package/dist/components/FloatingInput.d.ts.map +1 -0
- package/dist/components/FloatingInput.js +38 -0
- package/dist/components/FloatingInput.js.map +1 -0
- package/dist/components/Form.d.ts +22 -0
- package/dist/components/Form.d.ts.map +1 -0
- package/dist/components/Form.js +81 -0
- package/dist/components/Form.js.map +1 -0
- package/dist/components/Icon.d.ts +48 -0
- package/dist/components/Icon.d.ts.map +1 -0
- package/dist/components/Icon.js +46 -0
- package/dist/components/Icon.js.map +1 -0
- package/dist/components/Input.d.ts +12 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Input.js +25 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/LanguagePicker.d.ts +60 -0
- package/dist/components/LanguagePicker.d.ts.map +1 -0
- package/dist/components/LanguagePicker.js +45 -0
- package/dist/components/LanguagePicker.js.map +1 -0
- package/dist/components/Layout.d.ts +24 -0
- package/dist/components/Layout.d.ts.map +1 -0
- package/dist/components/Layout.js +104 -0
- package/dist/components/Layout.js.map +1 -0
- package/dist/components/Modal.d.ts +32 -0
- package/dist/components/Modal.d.ts.map +1 -0
- package/dist/components/Modal.js +235 -0
- package/dist/components/Modal.js.map +1 -0
- package/dist/components/PageHeader.d.ts +15 -0
- package/dist/components/PageHeader.d.ts.map +1 -0
- package/dist/components/PageHeader.js +20 -0
- package/dist/components/PageHeader.js.map +1 -0
- package/dist/components/PageShell.d.ts +15 -0
- package/dist/components/PageShell.d.ts.map +1 -0
- package/dist/components/PageShell.js +20 -0
- package/dist/components/PageShell.js.map +1 -0
- package/dist/components/Pagination.d.ts +12 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +78 -0
- package/dist/components/Pagination.js.map +1 -0
- package/dist/components/PanelClose.d.ts +40 -0
- package/dist/components/PanelClose.d.ts.map +1 -0
- package/dist/components/PanelClose.js +32 -0
- package/dist/components/PanelClose.js.map +1 -0
- package/dist/components/Progress.d.ts +45 -0
- package/dist/components/Progress.d.ts.map +1 -0
- package/dist/components/Progress.js +21 -0
- package/dist/components/Progress.js.map +1 -0
- package/dist/components/RadioGroup.d.ts +12 -0
- package/dist/components/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup.js +34 -0
- package/dist/components/RadioGroup.js.map +1 -0
- package/dist/components/Select.d.ts +12 -0
- package/dist/components/Select.d.ts.map +1 -0
- package/dist/components/Select.js +57 -0
- package/dist/components/Select.js.map +1 -0
- package/dist/components/Separator.d.ts +25 -0
- package/dist/components/Separator.d.ts.map +1 -0
- package/dist/components/Separator.js +18 -0
- package/dist/components/Separator.js.map +1 -0
- package/dist/components/SidebarUserCard.d.ts +60 -0
- package/dist/components/SidebarUserCard.d.ts.map +1 -0
- package/dist/components/SidebarUserCard.js +45 -0
- package/dist/components/SidebarUserCard.js.map +1 -0
- package/dist/components/Skeleton.d.ts +26 -0
- package/dist/components/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton.js +45 -0
- package/dist/components/Skeleton.js.map +1 -0
- package/dist/components/Spinner.d.ts +17 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +32 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/Switch.d.ts +12 -0
- package/dist/components/Switch.d.ts.map +1 -0
- package/dist/components/Switch.js +52 -0
- package/dist/components/Switch.js.map +1 -0
- package/dist/components/Table.d.ts +12 -0
- package/dist/components/Table.d.ts.map +1 -0
- package/dist/components/Table.js +53 -0
- package/dist/components/Table.js.map +1 -0
- package/dist/components/Tabs.d.ts +12 -0
- package/dist/components/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs.js +72 -0
- package/dist/components/Tabs.js.map +1 -0
- package/dist/components/Textarea.d.ts +12 -0
- package/dist/components/Textarea.d.ts.map +1 -0
- package/dist/components/Textarea.js +66 -0
- package/dist/components/Textarea.js.map +1 -0
- package/dist/components/ThemeToggle.d.ts +43 -0
- package/dist/components/ThemeToggle.d.ts.map +1 -0
- package/dist/components/ThemeToggle.js +30 -0
- package/dist/components/ThemeToggle.js.map +1 -0
- package/dist/components/Toast.d.ts +61 -0
- package/dist/components/Toast.d.ts.map +1 -0
- package/dist/components/Toast.js +159 -0
- package/dist/components/Toast.js.map +1 -0
- package/dist/components/Tooltip.d.ts +21 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +245 -0
- package/dist/components/Tooltip.js.map +1 -0
- package/dist/components/UserMenu.d.ts +59 -0
- package/dist/components/UserMenu.d.ts.map +1 -0
- package/dist/components/UserMenu.js +34 -0
- package/dist/components/UserMenu.js.map +1 -0
- package/dist/components/UserMenuPopover.d.ts +139 -0
- package/dist/components/UserMenuPopover.d.ts.map +1 -0
- package/dist/components/UserMenuPopover.js +173 -0
- package/dist/components/UserMenuPopover.js.map +1 -0
- package/dist/components/index.d.ts +43 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +43 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utilities/index.d.ts +8 -0
- package/dist/utilities/index.d.ts.map +1 -0
- package/dist/utilities/index.js +8 -0
- package/dist/utilities/index.js.map +1 -0
- package/dist/utilities/initials.d.ts +13 -0
- package/dist/utilities/initials.d.ts.map +1 -0
- package/dist/utilities/initials.js +23 -0
- package/dist/utilities/initials.js.map +1 -0
- package/dist/utilities/renderIcon.d.ts +21 -0
- package/dist/utilities/renderIcon.d.ts.map +1 -0
- package/dist/utilities/renderIcon.js +40 -0
- package/dist/utilities/renderIcon.js.map +1 -0
- package/dist/utilities.d.ts +12 -0
- package/dist/utilities.d.ts.map +1 -0
- package/dist/utilities.js +14 -0
- package/dist/utilities.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tabs component.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { TabsProps } from '@molecule/app-ui';
|
|
8
|
+
/**
|
|
9
|
+
* Tabs component.
|
|
10
|
+
*/
|
|
11
|
+
export declare const Tabs: React.ForwardRefExoticComponent<TabsProps<string> & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
+
//# sourceMappingURL=Tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA8C,MAAM,OAAO,CAAA;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAGjD;;GAEG;AACH,eAAO,MAAM,IAAI,0FA+GhB,CAAA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Tabs component.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { forwardRef, useId, useRef, useState } from 'react';
|
|
8
|
+
import { getClassMap } from '@molecule/app-ui';
|
|
9
|
+
/**
|
|
10
|
+
* Tabs component.
|
|
11
|
+
*/
|
|
12
|
+
export const Tabs = forwardRef(({ items, value, defaultValue, onChange, variant, size, fitted, className, style, testId }, ref) => {
|
|
13
|
+
const [internalValue, setInternalValue] = useState(defaultValue || items[0]?.value);
|
|
14
|
+
const activeValue = value !== undefined ? value : internalValue;
|
|
15
|
+
const cm = getClassMap();
|
|
16
|
+
// Per-instance id prefix: bare `tab-${value}` ids collided whenever two
|
|
17
|
+
// Tabs instances on one page shared a tab value (e.g. both have an
|
|
18
|
+
// "overview" tab) — aria-labelledby/aria-controls then resolved to the
|
|
19
|
+
// OTHER instance's elements.
|
|
20
|
+
const idBase = useId();
|
|
21
|
+
const tabRefs = useRef({});
|
|
22
|
+
const selectTab = (tabValue) => {
|
|
23
|
+
if (value === undefined) {
|
|
24
|
+
setInternalValue(tabValue);
|
|
25
|
+
}
|
|
26
|
+
onChange?.(tabValue);
|
|
27
|
+
};
|
|
28
|
+
// WAI-ARIA APG "automatic activation" tabs pattern: roving tabindex
|
|
29
|
+
// (only the active tab is a Tab stop — see `tabIndex` below) plus
|
|
30
|
+
// Left/Right/Home/End moving BOTH focus and the active tab, so keyboard
|
|
31
|
+
// users never have to Tab through every trigger to reach the one they
|
|
32
|
+
// want. Disabled tabs are skipped.
|
|
33
|
+
const handleKeyDown = (event) => {
|
|
34
|
+
const enabled = items.filter((item) => !item.disabled);
|
|
35
|
+
if (enabled.length === 0)
|
|
36
|
+
return;
|
|
37
|
+
const currentIndex = enabled.findIndex((item) => item.value === activeValue);
|
|
38
|
+
let nextIndex;
|
|
39
|
+
switch (event.key) {
|
|
40
|
+
case 'ArrowRight':
|
|
41
|
+
nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % enabled.length;
|
|
42
|
+
break;
|
|
43
|
+
case 'ArrowLeft':
|
|
44
|
+
nextIndex = currentIndex === -1 ? 0 : (currentIndex - 1 + enabled.length) % enabled.length;
|
|
45
|
+
break;
|
|
46
|
+
case 'Home':
|
|
47
|
+
nextIndex = 0;
|
|
48
|
+
break;
|
|
49
|
+
case 'End':
|
|
50
|
+
nextIndex = enabled.length - 1;
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
const nextValue = enabled[nextIndex].value;
|
|
57
|
+
selectTab(nextValue);
|
|
58
|
+
tabRefs.current[nextValue]?.focus();
|
|
59
|
+
};
|
|
60
|
+
const activeItem = items.find((item) => item.value === activeValue);
|
|
61
|
+
return (_jsxs("div", { ref: ref, className: className, style: style, "data-testid": testId, children: [_jsx("div", { className: cm.cn(cm.tabsList({ variant, size }), fitted && cm.tabsFitted), role: "tablist", onKeyDown: handleKeyDown, children: items.map((item) => {
|
|
62
|
+
const isActive = item.value === activeValue;
|
|
63
|
+
return (_jsxs("button", { ref: (node) => {
|
|
64
|
+
tabRefs.current[item.value] = node;
|
|
65
|
+
}, id: `${idBase}-tab-${item.value}`, type: "button", role: "tab", "aria-selected": isActive, "aria-controls": `${idBase}-tabpanel-${item.value}`, "data-state": isActive ? 'active' : 'inactive',
|
|
66
|
+
// Roving tabindex: only the active tab is a Tab stop —
|
|
67
|
+
// arrow keys (handled above) move focus among the rest.
|
|
68
|
+
tabIndex: isActive ? 0 : -1, disabled: item.disabled, onClick: () => selectTab(item.value), className: cm.cn(cm.tabsTrigger({ variant, size }), fitted && cm.tabTriggerFitted), children: [!!item.icon && (_jsx("span", { className: cm.tabTriggerIcon, children: item.icon })), item.label] }, item.value));
|
|
69
|
+
}) }), !!activeItem?.content && (_jsx("div", { role: "tabpanel", id: `${idBase}-tabpanel-${activeValue}`, "aria-labelledby": `${idBase}-tab-${activeValue}`, className: cm.tabsContent({ variant, size }), children: activeItem.content }))] }));
|
|
70
|
+
});
|
|
71
|
+
Tabs.displayName = 'Tabs';
|
|
72
|
+
//# sourceMappingURL=Tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Textarea component.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { TextareaProps } from '@molecule/app-ui';
|
|
8
|
+
/**
|
|
9
|
+
* Textarea component.
|
|
10
|
+
*/
|
|
11
|
+
export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
12
|
+
//# sourceMappingURL=Textarea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../src/components/Textarea.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAA;AAEhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGrD;;GAEG;AACH,eAAO,MAAM,QAAQ,2FA6HpB,CAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Textarea component.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { forwardRef, useCallback, useEffect, useId, useRef } from 'react';
|
|
8
|
+
import { getClassMap } from '@molecule/app-ui';
|
|
9
|
+
/**
|
|
10
|
+
* Textarea component.
|
|
11
|
+
*/
|
|
12
|
+
export const Textarea = forwardRef(({ size, label, error, hint, autoResize, minRows = 3, maxRows, className, style, testId, disabled, required, value, defaultValue, placeholder, name, id, rows, onChange, onFocus, onBlur, ...rest }, ref) => {
|
|
13
|
+
// Always track the node in internalRef (for autoResize) AND forward it to
|
|
14
|
+
// the caller's ref. The previous `(ref || internalRef) as RefObject` cast
|
|
15
|
+
// silently broke autoResize whenever the caller passed a CALLBACK ref
|
|
16
|
+
// (functions have no `.current`).
|
|
17
|
+
const internalRef = useRef(null);
|
|
18
|
+
const setRefs = useCallback((node) => {
|
|
19
|
+
internalRef.current = node;
|
|
20
|
+
if (typeof ref === 'function')
|
|
21
|
+
ref(node);
|
|
22
|
+
else if (ref)
|
|
23
|
+
ref.current = node;
|
|
24
|
+
}, [ref]);
|
|
25
|
+
const cm = getClassMap();
|
|
26
|
+
// Fall back to a generated id so label htmlFor / aria-describedby never
|
|
27
|
+
// point at `undefined-error` (which also collides across multiple
|
|
28
|
+
// id-less textareas on the same page).
|
|
29
|
+
const generatedId = useId();
|
|
30
|
+
const textareaId = id || name || generatedId;
|
|
31
|
+
const resize = useCallback(() => {
|
|
32
|
+
const element = internalRef.current;
|
|
33
|
+
if (!autoResize || !element)
|
|
34
|
+
return;
|
|
35
|
+
element.style.height = 'auto';
|
|
36
|
+
const lineHeight = parseInt(getComputedStyle(element).lineHeight) || 20;
|
|
37
|
+
const minHeight = minRows * lineHeight;
|
|
38
|
+
const maxHeight = maxRows ? maxRows * lineHeight : Infinity;
|
|
39
|
+
const newHeight = Math.min(Math.max(element.scrollHeight, minHeight), maxHeight);
|
|
40
|
+
element.style.height = `${newHeight}px`;
|
|
41
|
+
}, [autoResize, minRows, maxRows]);
|
|
42
|
+
// Controlled usage (value tracked by the caller) recomputes here.
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
resize();
|
|
45
|
+
}, [value, resize]);
|
|
46
|
+
// Uncontrolled usage (defaultValue + the user typing) never changes
|
|
47
|
+
// `value`, so the effect above never re-runs — autoResize silently did
|
|
48
|
+
// nothing for every uncontrolled textarea. Listening for real `input`
|
|
49
|
+
// events on the element itself catches keystrokes, paste, and IME
|
|
50
|
+
// composition regardless of whether the caller tracks `value`.
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
const element = internalRef.current;
|
|
53
|
+
if (!autoResize || !element)
|
|
54
|
+
return;
|
|
55
|
+
element.addEventListener('input', resize);
|
|
56
|
+
return () => element.removeEventListener('input', resize);
|
|
57
|
+
}, [autoResize, resize]);
|
|
58
|
+
const textareaClasses = cm.cn(cm.textarea({ error: !!error, size }), className);
|
|
59
|
+
return (_jsxs("div", { className: cm.inputWrapper, children: [label && (_jsx("label", { htmlFor: textareaId, className: cm.cn(cm.label({ required: !!required }), cm.labelBlock), children: label })), _jsx("textarea", { ref: setRefs, id: textareaId, name: name, value: value, defaultValue: defaultValue, placeholder: placeholder, disabled: disabled, required: required, rows: rows || minRows, "aria-invalid": !!error, "aria-describedby": error ? `${textareaId}-error` : hint ? `${textareaId}-hint` : undefined, className: textareaClasses,
|
|
60
|
+
// autoResize sizes the box to its content via inline height, but the
|
|
61
|
+
// bond's min-h class would floor it — neutralize it and let resize()
|
|
62
|
+
// enforce `minRows` instead. Caller style still wins.
|
|
63
|
+
style: autoResize ? { minHeight: 0, resize: 'none', ...style } : style, "data-testid": testId, onChange: onChange, onFocus: onFocus, onBlur: onBlur, ...rest }), error && (_jsx("p", { id: `${textareaId}-error`, className: cm.formError, children: error })), hint && !error && (_jsx("p", { id: `${textareaId}-hint`, className: cm.formHint, children: hint }))] }));
|
|
64
|
+
});
|
|
65
|
+
Textarea.displayName = 'Textarea';
|
|
66
|
+
//# sourceMappingURL=Textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../src/components/Textarea.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, JSX } from 'react';
|
|
2
|
+
import type { IconName } from '@molecule/app-icons';
|
|
3
|
+
/**
|
|
4
|
+
* Props for {@link ThemeToggle}.
|
|
5
|
+
*
|
|
6
|
+
* Extends standard `<button>` attributes so callers can pass any extra
|
|
7
|
+
* `data-*`, `aria-*`, event handler, or `style` prop without forking the
|
|
8
|
+
* component. The handful of explicitly named props below let apps swap
|
|
9
|
+
* the icon glyphs, label, or size without spreading attribute concerns.
|
|
10
|
+
*/
|
|
11
|
+
export interface ThemeToggleProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'aria-label' | 'aria-pressed' | 'onClick' | 'type'> {
|
|
12
|
+
/** i18n key for the `aria-label`. Defaults to `'theme.toggle'`. */
|
|
13
|
+
ariaLabelKey?: string;
|
|
14
|
+
/** Fallback `aria-label` if the i18n key is missing. Defaults to `'Toggle theme'`. */
|
|
15
|
+
ariaLabelDefault?: string;
|
|
16
|
+
/** Icon name to render in dark mode. Defaults to `'moon'`. */
|
|
17
|
+
darkIcon?: IconName;
|
|
18
|
+
/** Icon name to render in light mode. Defaults to `'sun'`. */
|
|
19
|
+
lightIcon?: IconName;
|
|
20
|
+
/** Pixel size for the rendered icon. Defaults to `20`. */
|
|
21
|
+
iconSize?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Button that flips the wired theme bond between light and dark.
|
|
25
|
+
*
|
|
26
|
+
* Reads `mode` and `toggleTheme` from `useTheme()` and shows the
|
|
27
|
+
* configured dark/light icon accordingly. Ships with molecule
|
|
28
|
+
* conventions out of the box:
|
|
29
|
+
*
|
|
30
|
+
* - `data-mol-id="theme-toggle"` for AI-agent / e2e selection
|
|
31
|
+
* - `data-mode={mode}` so tests can assert current state via DOM
|
|
32
|
+
* - `aria-pressed={mode === 'dark'}` for screen-reader state
|
|
33
|
+
* - `aria-label` from the `theme.toggle` i18n key (default `"Toggle theme"`)
|
|
34
|
+
*
|
|
35
|
+
* Every per-app variant the fleet was carrying — extra `data-*` attrs,
|
|
36
|
+
* additional `aria-*` flags, custom event handlers — is now absorbed
|
|
37
|
+
* via the spread of unknown props. Apps that need different icons or
|
|
38
|
+
* label text use the named props.
|
|
39
|
+
*
|
|
40
|
+
* @param props - {@link ThemeToggleProps}
|
|
41
|
+
*/
|
|
42
|
+
export declare function ThemeToggle({ ariaLabelKey, ariaLabelDefault, darkIcon, lightIcon, iconSize, className, ...rest }?: ThemeToggleProps): JSX.Element;
|
|
43
|
+
//# sourceMappingURL=ThemeToggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../src/components/ThemeToggle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAMnD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,YAAY,GAAG,cAAc,GAAG,SAAS,GAAG,MAAM,CACnD;IACC,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,QAAQ,CAAA;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,YAA6B,EAC7B,gBAAiC,EACjC,QAAiB,EACjB,SAAiB,EACjB,QAAa,EACb,SAAS,EACT,GAAG,IAAI,EACR,GAAE,gBAAqB,GAAG,GAAG,CAAC,OAAO,CAuBrC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTheme, useTranslation } from '@molecule/app-react';
|
|
3
|
+
import { getClassMap } from '@molecule/app-ui';
|
|
4
|
+
import { Icon } from './Icon.js';
|
|
5
|
+
/**
|
|
6
|
+
* Button that flips the wired theme bond between light and dark.
|
|
7
|
+
*
|
|
8
|
+
* Reads `mode` and `toggleTheme` from `useTheme()` and shows the
|
|
9
|
+
* configured dark/light icon accordingly. Ships with molecule
|
|
10
|
+
* conventions out of the box:
|
|
11
|
+
*
|
|
12
|
+
* - `data-mol-id="theme-toggle"` for AI-agent / e2e selection
|
|
13
|
+
* - `data-mode={mode}` so tests can assert current state via DOM
|
|
14
|
+
* - `aria-pressed={mode === 'dark'}` for screen-reader state
|
|
15
|
+
* - `aria-label` from the `theme.toggle` i18n key (default `"Toggle theme"`)
|
|
16
|
+
*
|
|
17
|
+
* Every per-app variant the fleet was carrying — extra `data-*` attrs,
|
|
18
|
+
* additional `aria-*` flags, custom event handlers — is now absorbed
|
|
19
|
+
* via the spread of unknown props. Apps that need different icons or
|
|
20
|
+
* label text use the named props.
|
|
21
|
+
*
|
|
22
|
+
* @param props - {@link ThemeToggleProps}
|
|
23
|
+
*/
|
|
24
|
+
export function ThemeToggle({ ariaLabelKey = 'theme.toggle', ariaLabelDefault = 'Toggle theme', darkIcon = 'moon', lightIcon = 'sun', iconSize = 20, className, ...rest } = {}) {
|
|
25
|
+
const cm = getClassMap();
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
const { mode, toggleTheme } = useTheme();
|
|
28
|
+
return (_jsx("button", { type: "button", "data-mol-id": "theme-toggle", "data-mode": mode, "aria-pressed": mode === 'dark', "aria-label": t(ariaLabelKey, {}, { defaultValue: ariaLabelDefault }), onClick: toggleTheme, className: cm.cn(cm.themeToggleButton, className), ...rest, children: mode === 'dark' ? (_jsx(Icon, { name: darkIcon, size: iconSize })) : (_jsx(Icon, { name: lightIcon, size: iconSize })) }));
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=ThemeToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeToggle.js","sourceRoot":"","sources":["../../src/components/ThemeToggle.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA0BhC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,YAAY,GAAG,cAAc,EAC7B,gBAAgB,GAAG,cAAc,EACjC,QAAQ,GAAG,MAAM,EACjB,SAAS,GAAG,KAAK,EACjB,QAAQ,GAAG,EAAE,EACb,SAAS,EACT,GAAG,IAAI,KACa,EAAE;IACtB,MAAM,EAAE,GAAG,WAAW,EAAE,CAAA;IACxB,MAAM,EAAE,CAAC,EAAE,GAAG,cAAc,EAAE,CAAA;IAC9B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAAA;IAExC,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,iBACD,cAAc,eACf,IAAI,kBACD,IAAI,KAAK,MAAM,gBACjB,CAAC,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC,EACnE,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,KAC7C,IAAI,YAEP,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CACjB,KAAC,IAAI,IAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAI,CACzC,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,IAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAI,CAC1C,GACM,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast component.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { ToastProps } from '@molecule/app-ui';
|
|
8
|
+
/**
|
|
9
|
+
* Single Toast component.
|
|
10
|
+
*
|
|
11
|
+
* The auto-dismiss countdown pauses on hover AND focus (WCAG 2.2.1) and
|
|
12
|
+
* resumes with whatever time was left — a slow reader or a keyboard/AT
|
|
13
|
+
* user interacting with the toast never has it disappear mid-read. The
|
|
14
|
+
* announced role follows `status`: `warning`/`error` get the assertive
|
|
15
|
+
* `role="alert"`; every other status (`info`, `success`, the default) gets
|
|
16
|
+
* the polite `role="status"` so routine confirmations don't interrupt a
|
|
17
|
+
* screen reader mid-sentence the way an assertive announcement does.
|
|
18
|
+
*/
|
|
19
|
+
export declare const Toast: React.ForwardRefExoticComponent<ToastProps & React.RefAttributes<HTMLDivElement>>;
|
|
20
|
+
/**
|
|
21
|
+
* Toast container for positioning toasts.
|
|
22
|
+
*/
|
|
23
|
+
interface ToastContainerProps {
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
position?: ToastProps['position'];
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Container that positions toasts on screen via a portal.
|
|
30
|
+
* @returns The rendered toast container element.
|
|
31
|
+
*/
|
|
32
|
+
export declare const ToastContainer: React.ForwardRefExoticComponent<ToastContainerProps & React.RefAttributes<HTMLDivElement>>;
|
|
33
|
+
/**
|
|
34
|
+
* Toast context for managing toasts globally.
|
|
35
|
+
*/
|
|
36
|
+
interface ToastContextValue {
|
|
37
|
+
toasts: (ToastProps & {
|
|
38
|
+
id: string;
|
|
39
|
+
})[];
|
|
40
|
+
addToast: (toast: Omit<ToastProps, 'onDismiss'>) => string;
|
|
41
|
+
removeToast: (id: string) => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Hook to access the toast context for adding and removing toasts.
|
|
45
|
+
* @returns The toast context value with toast management methods.
|
|
46
|
+
*/
|
|
47
|
+
export declare const useToast: () => ToastContextValue;
|
|
48
|
+
interface ToastProviderProps {
|
|
49
|
+
children: React.ReactNode;
|
|
50
|
+
position?: ToastProps['position'];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Provider component that manages global toast state.
|
|
54
|
+
* @param root0 - The component props.
|
|
55
|
+
* @param root0.children - The child elements to render within the provider.
|
|
56
|
+
* @param root0.position - The default position for toasts.
|
|
57
|
+
* @returns The rendered provider with toast container.
|
|
58
|
+
*/
|
|
59
|
+
export declare const ToastProvider: React.FC<ToastProviderProps>;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=Toast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/components/Toast.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAA;AAKd,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,kBAAkB,CAAA;AA4BhE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,mFAgIjB,CAAA;AAID;;GAEG;AACH,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAID;;;GAGG;AACH,eAAO,MAAM,cAAc,4FAa1B,CAAA;AAID;;GAEG;AACH,UAAU,iBAAiB;IACzB,MAAM,EAAE,CAAC,UAAU,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAA;IACvC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,KAAK,MAAM,CAAA;IAC1D,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAID;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAO,iBAU3B,CAAA;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAA;CAClC;AAID;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA0BtD,CAAA"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Toast component.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { createContext, forwardRef, useCallback, useContext, useEffect, useRef, useState, } from 'react';
|
|
8
|
+
import { createPortal } from 'react-dom';
|
|
9
|
+
import { t } from '@molecule/app-i18n';
|
|
10
|
+
import { getClassMap } from '@molecule/app-ui';
|
|
11
|
+
import { renderIcon } from '../utilities/renderIcon.js';
|
|
12
|
+
/**
|
|
13
|
+
* Map status to toast variant.
|
|
14
|
+
*/
|
|
15
|
+
const statusVariantMap = {
|
|
16
|
+
primary: 'default',
|
|
17
|
+
secondary: 'default',
|
|
18
|
+
success: 'success',
|
|
19
|
+
warning: 'warning',
|
|
20
|
+
error: 'error',
|
|
21
|
+
info: 'info',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Map toast status to icon name.
|
|
25
|
+
*/
|
|
26
|
+
const statusIconMap = {
|
|
27
|
+
info: 'info-circle',
|
|
28
|
+
success: 'check-circle',
|
|
29
|
+
warning: 'exclamation-triangle',
|
|
30
|
+
error: 'x-circle',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Single Toast component.
|
|
34
|
+
*
|
|
35
|
+
* The auto-dismiss countdown pauses on hover AND focus (WCAG 2.2.1) and
|
|
36
|
+
* resumes with whatever time was left — a slow reader or a keyboard/AT
|
|
37
|
+
* user interacting with the toast never has it disappear mid-read. The
|
|
38
|
+
* announced role follows `status`: `warning`/`error` get the assertive
|
|
39
|
+
* `role="alert"`; every other status (`info`, `success`, the default) gets
|
|
40
|
+
* the polite `role="status"` so routine confirmations don't interrupt a
|
|
41
|
+
* screen reader mid-sentence the way an assertive announcement does.
|
|
42
|
+
*/
|
|
43
|
+
export const Toast = forwardRef(({ children, title, description, status = 'info', duration = 5000, dismissible = true, onDismiss, position: _position = 'bottom-right', closeLabel, className, style, testId, }, ref) => {
|
|
44
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
45
|
+
const cm = getClassMap();
|
|
46
|
+
const variant = statusVariantMap[status] || 'default';
|
|
47
|
+
const iconName = statusIconMap[variant];
|
|
48
|
+
const statusIcon = iconName ? renderIcon(iconName, cm.iconMd) : null;
|
|
49
|
+
// Keep the latest onDismiss in a ref so the auto-dismiss timer depends
|
|
50
|
+
// ONLY on `duration`. With onDismiss in the effect deps, every parent
|
|
51
|
+
// re-render that recreates the callback (e.g. ToastProvider re-rendering
|
|
52
|
+
// as new toasts arrive) restarted the countdown — a busy toast stack
|
|
53
|
+
// never auto-dismissed.
|
|
54
|
+
const onDismissRef = useRef(onDismiss);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
onDismissRef.current = onDismiss;
|
|
57
|
+
}, [onDismiss]);
|
|
58
|
+
// WCAG 2.2.1 (Timing Adjustable): a countdown a slow reader or AT user
|
|
59
|
+
// cannot pause loses the message mid-read. `remainingRef` carries the
|
|
60
|
+
// time left across pause/resume cycles (hover in/out, focus in/out)
|
|
61
|
+
// instead of a fixed deadline.
|
|
62
|
+
const remainingRef = useRef(duration);
|
|
63
|
+
const startedAtRef = useRef(null);
|
|
64
|
+
const timerRef = useRef(undefined);
|
|
65
|
+
const clearTimer = useCallback(() => {
|
|
66
|
+
if (timerRef.current) {
|
|
67
|
+
clearTimeout(timerRef.current);
|
|
68
|
+
timerRef.current = undefined;
|
|
69
|
+
}
|
|
70
|
+
startedAtRef.current = null;
|
|
71
|
+
}, []);
|
|
72
|
+
const startTimer = useCallback((ms) => {
|
|
73
|
+
clearTimer();
|
|
74
|
+
if (ms <= 0)
|
|
75
|
+
return;
|
|
76
|
+
startedAtRef.current = Date.now();
|
|
77
|
+
timerRef.current = setTimeout(() => {
|
|
78
|
+
setIsVisible(false);
|
|
79
|
+
onDismissRef.current?.();
|
|
80
|
+
}, ms);
|
|
81
|
+
}, [clearTimer]);
|
|
82
|
+
const pauseTimer = useCallback(() => {
|
|
83
|
+
if (startedAtRef.current === null)
|
|
84
|
+
return;
|
|
85
|
+
const elapsed = Date.now() - startedAtRef.current;
|
|
86
|
+
remainingRef.current = Math.max(0, remainingRef.current - elapsed);
|
|
87
|
+
clearTimer();
|
|
88
|
+
}, [clearTimer]);
|
|
89
|
+
const resumeTimer = useCallback(() => {
|
|
90
|
+
if (remainingRef.current > 0)
|
|
91
|
+
startTimer(remainingRef.current);
|
|
92
|
+
}, [startTimer]);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
remainingRef.current = duration;
|
|
95
|
+
startTimer(duration);
|
|
96
|
+
return () => clearTimer();
|
|
97
|
+
}, [duration, startTimer, clearTimer]);
|
|
98
|
+
const handleDismiss = useCallback(() => {
|
|
99
|
+
setIsVisible(false);
|
|
100
|
+
onDismiss?.();
|
|
101
|
+
}, [onDismiss]);
|
|
102
|
+
if (!isVisible)
|
|
103
|
+
return null;
|
|
104
|
+
// Assertive announcement is appropriate for warnings/errors — an info or
|
|
105
|
+
// success toast interrupting a screen-reader user mid-sentence for a
|
|
106
|
+
// routine confirmation is the same over-announcing trap `role="alert"`
|
|
107
|
+
// creates everywhere it's used for non-urgent content.
|
|
108
|
+
const role = variant === 'warning' || variant === 'error' ? 'alert' : 'status';
|
|
109
|
+
return (_jsxs("div", { ref: ref, role: role, "data-state": "open", className: cm.cn(cm.toast({ variant }), className), style: style, "data-testid": testId, onMouseEnter: pauseTimer, onMouseLeave: resumeTimer, onFocus: pauseTimer, onBlur: resumeTimer, children: [statusIcon && _jsx("span", { className: cm.toastIconWrapper, children: statusIcon }), _jsxs("div", { className: cm.toastContentWrapper, children: [title && _jsx("div", { className: cm.toastTitle, children: title }), !!(description || children) && (_jsx("div", { className: cm.toastDescription, children: description || children }))] }), dismissible && (_jsx("button", { type: "button", onClick: handleDismiss, className: cm.toastClose, "aria-label": closeLabel ?? t('ui.toast.close', undefined, { defaultValue: 'Close' }), children: renderIcon('x-mark', cm.iconSm) }))] }));
|
|
110
|
+
});
|
|
111
|
+
Toast.displayName = 'Toast';
|
|
112
|
+
// positionClasses removed — use cm.toastContainer({ position }) instead
|
|
113
|
+
/**
|
|
114
|
+
* Container that positions toasts on screen via a portal.
|
|
115
|
+
* @returns The rendered toast container element.
|
|
116
|
+
*/
|
|
117
|
+
export const ToastContainer = forwardRef(({ children, position = 'bottom-right', className }, ref) => {
|
|
118
|
+
const cm = getClassMap();
|
|
119
|
+
const container = (_jsx("div", { ref: ref, className: cm.cn(cm.toastContainer({ position }), className), children: children }));
|
|
120
|
+
if (typeof document === 'undefined')
|
|
121
|
+
return null;
|
|
122
|
+
return createPortal(container, document.body);
|
|
123
|
+
});
|
|
124
|
+
ToastContainer.displayName = 'ToastContainer';
|
|
125
|
+
const ToastContext = createContext(null);
|
|
126
|
+
/**
|
|
127
|
+
* Hook to access the toast context for adding and removing toasts.
|
|
128
|
+
* @returns The toast context value with toast management methods.
|
|
129
|
+
*/
|
|
130
|
+
export const useToast = () => {
|
|
131
|
+
const context = useContext(ToastContext);
|
|
132
|
+
if (!context) {
|
|
133
|
+
throw new Error(t('react.error.useToastOutsideProvider', undefined, {
|
|
134
|
+
defaultValue: 'useToast must be used within a ToastProvider',
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
return context;
|
|
138
|
+
};
|
|
139
|
+
let toastCounter = 0;
|
|
140
|
+
/**
|
|
141
|
+
* Provider component that manages global toast state.
|
|
142
|
+
* @param root0 - The component props.
|
|
143
|
+
* @param root0.children - The child elements to render within the provider.
|
|
144
|
+
* @param root0.position - The default position for toasts.
|
|
145
|
+
* @returns The rendered provider with toast container.
|
|
146
|
+
*/
|
|
147
|
+
export const ToastProvider = ({ children, position = 'bottom-right', }) => {
|
|
148
|
+
const [toasts, setToasts] = useState([]);
|
|
149
|
+
const addToast = useCallback((toast) => {
|
|
150
|
+
const id = `toast-${++toastCounter}`;
|
|
151
|
+
setToasts((prev) => [...prev, { ...toast, id }]);
|
|
152
|
+
return id;
|
|
153
|
+
}, []);
|
|
154
|
+
const removeToast = useCallback((id) => {
|
|
155
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
156
|
+
}, []);
|
|
157
|
+
return (_jsxs(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [children, _jsx(ToastContainer, { position: position, children: toasts.map((toast) => (_jsx(Toast, { ...toast, onDismiss: () => removeToast(toast.id) }, toast.id))) })] }));
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=Toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.js","sourceRoot":"","sources":["../../src/components/Toast.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tooltip component.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { TooltipProps } from '@molecule/app-ui';
|
|
8
|
+
/**
|
|
9
|
+
* Tooltip component.
|
|
10
|
+
*
|
|
11
|
+
* `children` must be a single valid React element (e.g. one `<button>` or
|
|
12
|
+
* one custom component that forwards `aria-describedby`) for the tooltip's
|
|
13
|
+
* content to be programmatically associated with it — this is what lets a
|
|
14
|
+
* screen reader announce the tooltip text for the actually-focused control.
|
|
15
|
+
* A non-element `children` (plain text, a fragment, multiple nodes) still
|
|
16
|
+
* shows the tooltip visually on hover/focus, but without that association.
|
|
17
|
+
* `hasArrow` renders a small themed pointer at the resolved `placement`
|
|
18
|
+
* edge.
|
|
19
|
+
*/
|
|
20
|
+
export declare const Tooltip: React.ForwardRefExoticComponent<TooltipProps & React.RefAttributes<HTMLDivElement>>;
|
|
21
|
+
//# sourceMappingURL=Tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../src/components/Tooltip.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAA;AAGd,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAqHtE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,OAAO,qFAwKnB,CAAA"}
|