@tangible/ui 0.0.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/README.md +100 -0
- package/components/Accordion/Accordion.d.ts +22 -0
- package/components/Accordion/Accordion.js +192 -0
- package/components/Accordion/AccordionContext.d.ts +5 -0
- package/components/Accordion/AccordionContext.js +23 -0
- package/components/Accordion/index.d.ts +2 -0
- package/components/Accordion/index.js +1 -0
- package/components/Accordion/types.d.ts +61 -0
- package/components/Accordion/types.js +1 -0
- package/components/Avatar/Avatar.d.ts +11 -0
- package/components/Avatar/Avatar.js +67 -0
- package/components/Avatar/AvatarGroup.d.ts +11 -0
- package/components/Avatar/AvatarGroup.js +45 -0
- package/components/Avatar/index.d.ts +9 -0
- package/components/Avatar/index.js +7 -0
- package/components/Avatar/types.d.ts +44 -0
- package/components/Avatar/types.js +12 -0
- package/components/Button/Button.d.ts +4 -0
- package/components/Button/Button.js +33 -0
- package/components/Button/index.d.ts +2 -0
- package/components/Button/index.js +1 -0
- package/components/Button/types.d.ts +127 -0
- package/components/Button/types.js +1 -0
- package/components/Card/Card.d.ts +29 -0
- package/components/Card/Card.js +47 -0
- package/components/Card/index.d.ts +2 -0
- package/components/Card/index.js +1 -0
- package/components/Chip/Chip.d.ts +24 -0
- package/components/Chip/Chip.js +37 -0
- package/components/Chip/index.d.ts +2 -0
- package/components/Chip/index.js +1 -0
- package/components/Chips/Chips.d.ts +31 -0
- package/components/Chips/Chips.js +21 -0
- package/components/Chips/index.d.ts +2 -0
- package/components/Chips/index.js +1 -0
- package/components/ContentIndicator/ContentIndicator.d.ts +2 -0
- package/components/ContentIndicator/ContentIndicator.js +21 -0
- package/components/ContentIndicator/index.d.ts +2 -0
- package/components/ContentIndicator/index.js +1 -0
- package/components/ContentIndicator/types.d.ts +57 -0
- package/components/ContentIndicator/types.js +1 -0
- package/components/Dropdown/Dropdown.d.ts +31 -0
- package/components/Dropdown/Dropdown.js +219 -0
- package/components/Dropdown/DropdownContext.d.ts +3 -0
- package/components/Dropdown/DropdownContext.js +9 -0
- package/components/Dropdown/index.d.ts +2 -0
- package/components/Dropdown/index.js +1 -0
- package/components/Dropdown/types.d.ts +102 -0
- package/components/Dropdown/types.js +8 -0
- package/components/Icon/Icon.d.ts +22 -0
- package/components/Icon/Icon.js +24 -0
- package/components/Icon/index.d.ts +2 -0
- package/components/Icon/index.js +1 -0
- package/components/IconButton/IconButton.d.ts +2 -0
- package/components/IconButton/IconButton.js +50 -0
- package/components/IconButton/index.d.ts +2 -0
- package/components/IconButton/index.js +1 -0
- package/components/IconButton/types.d.ts +79 -0
- package/components/IconButton/types.js +1 -0
- package/components/Modal/Modal.d.ts +52 -0
- package/components/Modal/Modal.js +133 -0
- package/components/Modal/context.d.ts +6 -0
- package/components/Modal/context.js +9 -0
- package/components/Modal/index.d.ts +2 -0
- package/components/Modal/index.js +1 -0
- package/components/Notice/Notice.d.ts +93 -0
- package/components/Notice/Notice.js +144 -0
- package/components/Notice/index.d.ts +2 -0
- package/components/Notice/index.js +1 -0
- package/components/OverlapStack/OverlapStack.d.ts +44 -0
- package/components/OverlapStack/OverlapStack.js +41 -0
- package/components/OverlapStack/index.d.ts +2 -0
- package/components/OverlapStack/index.js +1 -0
- package/components/Pager/Pager.d.ts +26 -0
- package/components/Pager/Pager.js +151 -0
- package/components/Pager/index.d.ts +2 -0
- package/components/Pager/index.js +1 -0
- package/components/Progress/Progress.d.ts +2 -0
- package/components/Progress/Progress.js +100 -0
- package/components/Progress/index.d.ts +4 -0
- package/components/Progress/index.js +2 -0
- package/components/Progress/types.d.ts +251 -0
- package/components/Progress/types.js +1 -0
- package/components/Progress/useProgressSegments.d.ts +40 -0
- package/components/Progress/useProgressSegments.js +42 -0
- package/components/Rating/Rating.d.ts +32 -0
- package/components/Rating/Rating.js +74 -0
- package/components/Rating/index.d.ts +2 -0
- package/components/Rating/index.js +1 -0
- package/components/SegmentedControl/SegmentedControl.d.ts +10 -0
- package/components/SegmentedControl/SegmentedControl.js +183 -0
- package/components/SegmentedControl/SegmentedControlContext.d.ts +3 -0
- package/components/SegmentedControl/SegmentedControlContext.js +9 -0
- package/components/SegmentedControl/index.d.ts +2 -0
- package/components/SegmentedControl/index.js +1 -0
- package/components/SegmentedControl/types.d.ts +63 -0
- package/components/SegmentedControl/types.js +1 -0
- package/components/Sidebar/Sidebar.d.ts +17 -0
- package/components/Sidebar/Sidebar.js +107 -0
- package/components/Sidebar/index.d.ts +2 -0
- package/components/Sidebar/index.js +1 -0
- package/components/Sidebar/types.d.ts +65 -0
- package/components/Sidebar/types.js +4 -0
- package/components/StepIndicator/StepIndicator.d.ts +2 -0
- package/components/StepIndicator/StepIndicator.js +64 -0
- package/components/StepIndicator/index.d.ts +2 -0
- package/components/StepIndicator/index.js +1 -0
- package/components/StepIndicator/types.d.ts +68 -0
- package/components/StepIndicator/types.js +1 -0
- package/components/StepList/StepList.d.ts +12 -0
- package/components/StepList/StepList.js +59 -0
- package/components/StepList/StepListContext.d.ts +3 -0
- package/components/StepList/StepListContext.js +9 -0
- package/components/StepList/index.d.ts +2 -0
- package/components/StepList/index.js +1 -0
- package/components/StepList/types.d.ts +91 -0
- package/components/StepList/types.js +4 -0
- package/components/Table/BulkActionsBar.d.ts +12 -0
- package/components/Table/BulkActionsBar.js +9 -0
- package/components/Table/DataTable.d.ts +35 -0
- package/components/Table/DataTable.js +184 -0
- package/components/Table/Pagination.d.ts +13 -0
- package/components/Table/Pagination.js +13 -0
- package/components/Table/index.d.ts +2 -0
- package/components/Table/index.js +1 -0
- package/components/Tabs/Tabs.d.ts +23 -0
- package/components/Tabs/Tabs.js +309 -0
- package/components/Tabs/TabsContext.d.ts +3 -0
- package/components/Tabs/TabsContext.js +12 -0
- package/components/Tabs/index.d.ts +2 -0
- package/components/Tabs/index.js +1 -0
- package/components/Tabs/types.d.ts +75 -0
- package/components/Tabs/types.js +1 -0
- package/components/Toolbar/Toolbar.d.ts +18 -0
- package/components/Toolbar/Toolbar.js +241 -0
- package/components/Toolbar/index.d.ts +2 -0
- package/components/Toolbar/index.js +1 -0
- package/components/Toolbar/types.d.ts +28 -0
- package/components/Toolbar/types.js +1 -0
- package/components/Tooltip/Tooltip.d.ts +15 -0
- package/components/Tooltip/Tooltip.js +166 -0
- package/components/Tooltip/TooltipContext.d.ts +15 -0
- package/components/Tooltip/TooltipContext.js +25 -0
- package/components/Tooltip/index.d.ts +2 -0
- package/components/Tooltip/index.js +1 -0
- package/components/Tooltip/types.d.ts +85 -0
- package/components/Tooltip/types.js +8 -0
- package/components/index.d.ts +52 -0
- package/components/index.js +26 -0
- package/constants.d.ts +16 -0
- package/constants.js +16 -0
- package/icons/cred/index.d.ts +31 -0
- package/icons/cred/index.js +136 -0
- package/icons/icons.svg +155 -0
- package/icons/lms/index.d.ts +21 -0
- package/icons/lms/index.js +81 -0
- package/icons/manifest.json +1226 -0
- package/icons/player/index.d.ts +55 -0
- package/icons/player/index.js +268 -0
- package/icons/reaction/index.d.ts +79 -0
- package/icons/reaction/index.js +400 -0
- package/icons/registry.d.ts +316 -0
- package/icons/registry.js +163 -0
- package/icons/system/index.d.ts +155 -0
- package/icons/system/index.js +818 -0
- package/package.json +121 -0
- package/styles/all.css +1 -0
- package/styles/all.expanded.css +4137 -0
- package/styles/all.expanded.unlayered.css +4137 -0
- package/styles/all.unlayered.css +1 -0
- package/styles/components/_bundle.scss +51 -0
- package/styles/components/index.scss +1 -0
- package/styles/components/input/index.scss +248 -0
- package/styles/index.scss +71 -0
- package/styles/system/_constants.scss +12 -0
- package/styles/system/_motion.scss +47 -0
- package/styles/system/_palette-fns.scss +10 -0
- package/styles/system/_palettes.scss +80 -0
- package/styles/system/_tokens.scss +249 -0
- package/styles/system/index.scss +4 -0
- package/styles/utilities/_index.scss +373 -0
- package/tui-manifest.json +1858 -0
- package/types/index.d.ts +2 -0
- package/types/index.js +1 -0
- package/types/index.ts +2 -0
- package/types/sizes.d.ts +17 -0
- package/types/sizes.js +10 -0
- package/types/sizes.ts +21 -0
- package/types/svg.d.ts +5 -0
- package/types/themes.d.ts +14 -0
- package/types/themes.js +9 -0
- package/types/themes.ts +17 -0
- package/utils/color/contrast.d.ts +33 -0
- package/utils/color/contrast.js +88 -0
- package/utils/color-scheme.d.ts +25 -0
- package/utils/color-scheme.js +55 -0
- package/utils/compose-refs.d.ts +17 -0
- package/utils/compose-refs.js +38 -0
- package/utils/cx.d.ts +12 -0
- package/utils/cx.js +14 -0
- package/utils/focus-trap.d.ts +40 -0
- package/utils/focus-trap.js +93 -0
- package/utils/index.d.ts +10 -0
- package/utils/index.js +16 -0
- package/utils/math.d.ts +4 -0
- package/utils/math.js +19 -0
- package/utils/merge-props.d.ts +25 -0
- package/utils/merge-props.js +60 -0
- package/utils/polymorphic.d.ts +28 -0
- package/utils/polymorphic.js +44 -0
- package/utils/portal.d.ts +11 -0
- package/utils/portal.js +105 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import { cx } from '../../utils/cx.js';
|
|
4
|
+
import { Icon } from '../Icon/index.js';
|
|
5
|
+
import { getSafeRel } from '../../utils/polymorphic.js';
|
|
6
|
+
export const Button = forwardRef(({ label, children, size = 'md', theme = 'primary', variant = 'solid', fullWidth, disabled = false, loading = false, leftIconName, rightIconName, leftIcon, rightIcon, iconSize = 'sm', className, target, rel, onClick, style, ...rest }, ref) => {
|
|
7
|
+
const isLink = typeof rest.href === 'string';
|
|
8
|
+
const isDisabled = disabled || loading;
|
|
9
|
+
// Normalize destructive → danger for CSS class
|
|
10
|
+
const themeClass = theme === 'destructive' ? 'danger' : theme;
|
|
11
|
+
const classes = cx('tui-button', `is-size-${size}`, `is-theme-${themeClass}`, variant !== 'solid' && `is-style-${variant}`, fullWidth && 'is-width-full', isDisabled && 'is-disabled', className);
|
|
12
|
+
// Icon size: pass string sizes to Icon component
|
|
13
|
+
const iconSizeForIcon = typeof iconSize === 'string' ? iconSize : undefined;
|
|
14
|
+
const Left = leftIcon ?? (leftIconName ? _jsx(Icon, { name: leftIconName, size: iconSizeForIcon }) : null);
|
|
15
|
+
const Right = rightIcon ?? (rightIconName ? _jsx(Icon, { name: rightIconName, size: iconSizeForIcon }) : null);
|
|
16
|
+
const content = label != null ? (_jsxs(_Fragment, { children: [Left, _jsx("span", { children: label }), Right] })) : (_jsxs(_Fragment, { children: [Left, children, Right] }));
|
|
17
|
+
if (isLink) {
|
|
18
|
+
const { href, tabIndex, ...anchorRest } = rest;
|
|
19
|
+
const safeRel = getSafeRel(target, rel);
|
|
20
|
+
const handleClick = (e) => {
|
|
21
|
+
if (isDisabled) {
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
e.stopPropagation();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
onClick?.(e);
|
|
27
|
+
};
|
|
28
|
+
return (_jsx("a", { ref: ref, href: isDisabled ? undefined : href, className: classes, "aria-disabled": isDisabled || undefined, "aria-busy": loading || undefined, tabIndex: isDisabled ? -1 : tabIndex, onClick: handleClick, "data-loading": loading || undefined, target: target, rel: safeRel, style: style, ...anchorRest, children: content }));
|
|
29
|
+
}
|
|
30
|
+
const buttonRest = rest;
|
|
31
|
+
return (_jsx("button", { ref: ref, type: buttonRest.type ?? 'button', className: classes, disabled: isDisabled, "aria-disabled": isDisabled || undefined, "aria-busy": loading || undefined, onClick: onClick, "data-loading": loading || undefined, style: style, ...buttonRest, children: content }));
|
|
32
|
+
});
|
|
33
|
+
Button.displayName = 'Button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Button } from './Button.js';
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { IconName } from '../../icons/registry';
|
|
2
|
+
import type { Size, ThemeIntent } from '../../types';
|
|
3
|
+
export type { Size };
|
|
4
|
+
/**
|
|
5
|
+
* Semantic color themes.
|
|
6
|
+
* - `'primary'`: Primary action (default)
|
|
7
|
+
* - `'secondary'`: Secondary/neutral action
|
|
8
|
+
* - `'danger'`: Destructive action
|
|
9
|
+
* - `'destructive'`: Alias for danger
|
|
10
|
+
*/
|
|
11
|
+
export type Theme = ThemeIntent | 'destructive';
|
|
12
|
+
/**
|
|
13
|
+
* Visual style variants.
|
|
14
|
+
* - `'solid'`: Filled background (default)
|
|
15
|
+
* - `'outline'`: Border only, transparent background
|
|
16
|
+
* - `'ghost'`: Transparent, shows background on hover
|
|
17
|
+
* - `'link'`: Text-link styling, no background
|
|
18
|
+
*/
|
|
19
|
+
export type Variant = 'solid' | 'outline' | 'ghost' | 'link';
|
|
20
|
+
type CommonProps = {
|
|
21
|
+
/**
|
|
22
|
+
* Button label text. If provided, renders as the button content.
|
|
23
|
+
* Use this for simple text buttons.
|
|
24
|
+
*/
|
|
25
|
+
label?: React.ReactNode;
|
|
26
|
+
/**
|
|
27
|
+
* Rich content for the button. Used when label is not provided.
|
|
28
|
+
* Use this for buttons with custom markup.
|
|
29
|
+
*/
|
|
30
|
+
children?: React.ReactNode;
|
|
31
|
+
/**
|
|
32
|
+
* Size of the button.
|
|
33
|
+
* @default 'md'
|
|
34
|
+
*/
|
|
35
|
+
size?: Size;
|
|
36
|
+
/**
|
|
37
|
+
* Semantic color theme.
|
|
38
|
+
* Note: Defaults to 'primary' (unlike IconButton which defaults to 'secondary')
|
|
39
|
+
* because Buttons are typically primary CTAs.
|
|
40
|
+
* @default 'primary'
|
|
41
|
+
*/
|
|
42
|
+
theme?: Theme;
|
|
43
|
+
/**
|
|
44
|
+
* Visual style variant.
|
|
45
|
+
* @default 'solid'
|
|
46
|
+
*/
|
|
47
|
+
variant?: Variant;
|
|
48
|
+
/**
|
|
49
|
+
* Make button full width of container.
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
fullWidth?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Disabled state. Prevents interaction.
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Loading state. Shows spinner and prevents interaction.
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
loading?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Link target (for anchor variant).
|
|
65
|
+
*/
|
|
66
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
67
|
+
/**
|
|
68
|
+
* Link rel attribute (for anchor variant).
|
|
69
|
+
*/
|
|
70
|
+
rel?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Click handler. Works for both button and anchor variants.
|
|
73
|
+
*/
|
|
74
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;
|
|
75
|
+
/**
|
|
76
|
+
* Icon to display before the label.
|
|
77
|
+
* Use icon registry paths like "system/check".
|
|
78
|
+
* @example leftIconName="system/check"
|
|
79
|
+
*/
|
|
80
|
+
leftIconName?: IconName;
|
|
81
|
+
/**
|
|
82
|
+
* Icon to display after the label.
|
|
83
|
+
* Use icon registry paths like "system/chevron-right".
|
|
84
|
+
* @example rightIconName="system/chevron-right"
|
|
85
|
+
*/
|
|
86
|
+
rightIconName?: IconName;
|
|
87
|
+
/**
|
|
88
|
+
* Custom left icon element. Overrides leftIconName.
|
|
89
|
+
*/
|
|
90
|
+
leftIcon?: React.ReactNode;
|
|
91
|
+
/**
|
|
92
|
+
* Custom right icon element. Overrides rightIconName.
|
|
93
|
+
*/
|
|
94
|
+
rightIcon?: React.ReactNode;
|
|
95
|
+
/**
|
|
96
|
+
* Size of icons.
|
|
97
|
+
* @default 'sm'
|
|
98
|
+
*/
|
|
99
|
+
iconSize?: Size;
|
|
100
|
+
/**
|
|
101
|
+
* Additional CSS class names.
|
|
102
|
+
* Note: Use sparingly. Prefer component API tokens for customization.
|
|
103
|
+
*/
|
|
104
|
+
className?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Inline styles.
|
|
107
|
+
*/
|
|
108
|
+
style?: React.CSSProperties;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Props when Button renders as a <button> element.
|
|
112
|
+
*/
|
|
113
|
+
export type ButtonAsButton = CommonProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'disabled' | 'children'> & {
|
|
114
|
+
href?: undefined;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Props when Button renders as an <a> element.
|
|
118
|
+
*/
|
|
119
|
+
export type ButtonAsAnchor = CommonProps & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
|
|
120
|
+
/** URL for the link. When provided, Button renders as <a>. */
|
|
121
|
+
href: string;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Button component props.
|
|
125
|
+
* Renders as <button> by default, or <a> when href is provided.
|
|
126
|
+
*/
|
|
127
|
+
export type ButtonProps = ButtonAsButton | ButtonAsAnchor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { JSX } from 'react';
|
|
3
|
+
type RootAs = 'article' | 'section' | 'div';
|
|
4
|
+
type CommonProps = {
|
|
5
|
+
inline?: boolean;
|
|
6
|
+
elevated?: boolean;
|
|
7
|
+
interactive?: boolean;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: React.CSSProperties;
|
|
11
|
+
};
|
|
12
|
+
export type CardRootProps<TAs extends RootAs = 'article'> = CommonProps & {
|
|
13
|
+
as?: TAs;
|
|
14
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
};
|
|
17
|
+
type SlotProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
18
|
+
className?: string;
|
|
19
|
+
children?: React.ReactNode;
|
|
20
|
+
};
|
|
21
|
+
type CardCompound = {
|
|
22
|
+
<TAs extends RootAs = 'article'>(props: CardRootProps<TAs> & Omit<React.ComponentPropsWithoutRef<TAs>, keyof CardRootProps>): JSX.Element;
|
|
23
|
+
Head: React.FC<SlotProps>;
|
|
24
|
+
Body: React.FC<SlotProps>;
|
|
25
|
+
Foot: React.FC<SlotProps>;
|
|
26
|
+
Link: React.FC<React.AnchorHTMLAttributes<HTMLAnchorElement>>;
|
|
27
|
+
};
|
|
28
|
+
export declare const Card: CardCompound;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { forwardRef, useCallback } from 'react';
|
|
3
|
+
import { cx } from '../../utils/cx.js';
|
|
4
|
+
export const Card = forwardRef(function Card({ as = 'article', inline, elevated, interactive, disabled, className, style, onClick, children, ...rest }, ref) {
|
|
5
|
+
const Tag = as;
|
|
6
|
+
// Determine if this card is clickable (needs button semantics)
|
|
7
|
+
const isClickable = (interactive || onClick) && !disabled;
|
|
8
|
+
// Keyboard handler for interactive cards
|
|
9
|
+
const handleKeyDown = useCallback((e) => {
|
|
10
|
+
if (!isClickable || !onClick)
|
|
11
|
+
return;
|
|
12
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
onClick(e);
|
|
15
|
+
}
|
|
16
|
+
}, [isClickable, onClick]);
|
|
17
|
+
const classes = cx('tui-card', inline && 'is-layout-inline', elevated && 'is-style-elevated', interactive && 'has-interaction', className);
|
|
18
|
+
// Button semantics for clickable cards
|
|
19
|
+
const buttonProps = isClickable
|
|
20
|
+
? {
|
|
21
|
+
role: 'button',
|
|
22
|
+
tabIndex: 0,
|
|
23
|
+
onKeyDown: handleKeyDown,
|
|
24
|
+
}
|
|
25
|
+
: {};
|
|
26
|
+
return (_jsx(Tag, { ref: ref, className: classes, style: style, "aria-disabled": disabled || undefined, onClick: disabled ? undefined : onClick, ...buttonProps, ...rest, children: _jsx("div", { className: "tui-card__inner", children: children }) }));
|
|
27
|
+
});
|
|
28
|
+
function CardHead({ className, children, ...rest }) {
|
|
29
|
+
return (_jsx("div", { className: cx('tui-card__head', className), ...rest, children: children }));
|
|
30
|
+
}
|
|
31
|
+
CardHead.displayName = 'Card.Head';
|
|
32
|
+
function CardBody({ className, children, ...rest }) {
|
|
33
|
+
return (_jsx("div", { className: cx('tui-card__body', className), ...rest, children: children }));
|
|
34
|
+
}
|
|
35
|
+
CardBody.displayName = 'Card.Body';
|
|
36
|
+
function CardFoot({ className, children, ...rest }) {
|
|
37
|
+
return (_jsx("div", { className: cx('tui-card__foot', className), ...rest, children: children }));
|
|
38
|
+
}
|
|
39
|
+
CardFoot.displayName = 'Card.Foot';
|
|
40
|
+
function CardLink({ className, children, rel, target, ...rest }) {
|
|
41
|
+
return (_jsx("a", { className: cx('tui-stretched-link', className), rel: target === '_blank' ? ['noopener', 'noreferrer', rel].filter(Boolean).join(' ') : rel, target: target, ...rest, children: children }));
|
|
42
|
+
}
|
|
43
|
+
CardLink.displayName = 'Card.Link';
|
|
44
|
+
Card.Head = CardHead;
|
|
45
|
+
Card.Body = CardBody;
|
|
46
|
+
Card.Foot = CardFoot;
|
|
47
|
+
Card.Link = CardLink;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Card } from './Card.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { SizeCompact, Theme as ThemeFull } from '../../types';
|
|
3
|
+
type Size = SizeCompact;
|
|
4
|
+
type Theme = ThemeFull;
|
|
5
|
+
type Variant = 'default' | 'outline' | 'ghost' | 'solid' | 'flush';
|
|
6
|
+
export type ChipProps = {
|
|
7
|
+
as?: 'span' | 'div' | 'a';
|
|
8
|
+
href?: string;
|
|
9
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
10
|
+
rel?: string;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
size?: Size;
|
|
13
|
+
theme?: Theme;
|
|
14
|
+
variant?: Variant;
|
|
15
|
+
selected?: boolean;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
interactive?: boolean;
|
|
18
|
+
className?: string;
|
|
19
|
+
leftIcon?: React.ReactNode;
|
|
20
|
+
rightIcon?: React.ReactNode;
|
|
21
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
22
|
+
} & Omit<React.HTMLAttributes<HTMLSpanElement>, 'onClick'>;
|
|
23
|
+
export declare function Chip({ as, href, target, rel, children, size, theme, variant, selected, disabled, interactive, className, leftIcon, rightIcon, onClick, ...rest }: ChipProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { cx } from '../../utils/cx.js';
|
|
5
|
+
export function Chip({ as = 'span', href, target, rel, children, size = 'md', theme = 'secondary', variant = 'default', selected, disabled, interactive, className, leftIcon, rightIcon, onClick, ...rest }) {
|
|
6
|
+
const Tag = (as === 'a' ? 'a' : as);
|
|
7
|
+
// Determine if this chip is clickable (needs button semantics)
|
|
8
|
+
const isClickable = (interactive || onClick) && !disabled;
|
|
9
|
+
// Keyboard handler for interactive chips
|
|
10
|
+
const handleKeyDown = useCallback((e) => {
|
|
11
|
+
if (!isClickable || !onClick)
|
|
12
|
+
return;
|
|
13
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
14
|
+
e.preventDefault();
|
|
15
|
+
onClick(e);
|
|
16
|
+
}
|
|
17
|
+
}, [isClickable, onClick]);
|
|
18
|
+
const classes = cx('tui-chip', size && `is-size-${size}`, theme && `is-theme-${theme}`, variant !== 'default' && `is-style-${variant}`, selected && 'is-selected', interactive && 'is-interactive', className);
|
|
19
|
+
const anchorProps = as === 'a'
|
|
20
|
+
? {
|
|
21
|
+
href: disabled ? undefined : href ?? '#',
|
|
22
|
+
target,
|
|
23
|
+
rel,
|
|
24
|
+
'aria-disabled': disabled || undefined,
|
|
25
|
+
tabIndex: disabled ? -1 : undefined,
|
|
26
|
+
}
|
|
27
|
+
: { 'aria-disabled': disabled || undefined };
|
|
28
|
+
// Button semantics for non-anchor clickable chips
|
|
29
|
+
const buttonProps = as !== 'a' && isClickable
|
|
30
|
+
? {
|
|
31
|
+
role: 'button',
|
|
32
|
+
tabIndex: 0,
|
|
33
|
+
onKeyDown: handleKeyDown,
|
|
34
|
+
}
|
|
35
|
+
: {};
|
|
36
|
+
return (_jsxs(Tag, { className: classes, ...anchorProps, ...buttonProps, onClick: disabled ? undefined : onClick, ...rest, children: [leftIcon && leftIcon, _jsx("span", { className: "tui-chip__text", children: children }), rightIcon && rightIcon] }));
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Chip } from './Chip.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SizeCompact, Theme as ThemeFull } from '../../types';
|
|
3
|
+
type Size = SizeCompact;
|
|
4
|
+
type Theme = ThemeFull;
|
|
5
|
+
type Variant = 'default' | 'outline' | 'ghost' | 'solid' | 'flush';
|
|
6
|
+
export type ChipOption = {
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
as?: 'a' | 'span' | 'div';
|
|
9
|
+
href?: string;
|
|
10
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
11
|
+
rel?: string;
|
|
12
|
+
size?: Size;
|
|
13
|
+
theme?: Theme;
|
|
14
|
+
variant?: Variant;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
leftIcon?: React.ReactNode;
|
|
18
|
+
rightIcon?: React.ReactNode;
|
|
19
|
+
};
|
|
20
|
+
export type ChipsProps = {
|
|
21
|
+
name?: string;
|
|
22
|
+
options: ChipOption[];
|
|
23
|
+
/** Gap between chips */
|
|
24
|
+
density?: 'xs' | 'sm' | 'md';
|
|
25
|
+
direction?: 'inline' | 'stack';
|
|
26
|
+
alignment?: 'start' | 'center' | 'end';
|
|
27
|
+
className?: string;
|
|
28
|
+
role?: React.AriaRole;
|
|
29
|
+
};
|
|
30
|
+
export declare function Chips({ name, options, density, direction, alignment, className, role }: ChipsProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Chip } from '../Chip/index.js';
|
|
4
|
+
const DENSITY_MAP = {
|
|
5
|
+
xs: 'var(--tui-spacing-xs)',
|
|
6
|
+
sm: 'var(--tui-spacing-sm)',
|
|
7
|
+
md: 'var(--tui-spacing-md)',
|
|
8
|
+
};
|
|
9
|
+
export function Chips({ name, options, density = 'sm', direction = 'inline', alignment, className, role = 'group' }) {
|
|
10
|
+
const isInline = direction === 'inline';
|
|
11
|
+
const style = {
|
|
12
|
+
display: 'flex',
|
|
13
|
+
flexDirection: isInline ? 'row' : 'column',
|
|
14
|
+
flexWrap: isInline ? 'wrap' : undefined,
|
|
15
|
+
gap: DENSITY_MAP[density],
|
|
16
|
+
justifyContent: isInline && alignment ? alignment : undefined,
|
|
17
|
+
alignItems: !isInline && alignment ? alignment : undefined,
|
|
18
|
+
marginBlockEnd: 'var(--tui-spacing-sm)',
|
|
19
|
+
};
|
|
20
|
+
return (_jsx("div", { role: role, className: className, "data-chips-name": name, style: style, children: options.map((o) => (_jsx(Chip, { as: o.as ?? (o.href ? 'a' : 'span'), href: o.href, target: o.target, rel: o.rel, size: o.size, theme: o.theme, variant: o.variant, disabled: o.disabled, className: o.className, leftIcon: o.leftIcon, rightIcon: o.rightIcon, children: o.label }))) }));
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Chips } from './Chips.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '../Icon/index.js';
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Component
|
|
5
|
+
// =============================================================================
|
|
6
|
+
export function ContentIndicator(props) {
|
|
7
|
+
const { icon, size = 'sm', theme = 'default', variant = 'ring', label, className, } = props;
|
|
8
|
+
// Build class names
|
|
9
|
+
const rootClassName = [
|
|
10
|
+
'tui-content-indicator',
|
|
11
|
+
`is-size-${size}`,
|
|
12
|
+
`is-theme-${theme}`,
|
|
13
|
+
`is-variant-${variant}`,
|
|
14
|
+
className,
|
|
15
|
+
]
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join(' ');
|
|
18
|
+
// If no label, the icon is decorative and the whole element is presentational
|
|
19
|
+
const isDecorative = !label;
|
|
20
|
+
return (_jsx("div", { className: rootClassName, role: isDecorative ? 'presentation' : 'img', "aria-label": label, "aria-hidden": isDecorative || undefined, children: _jsx("div", { className: "tui-content-indicator__circle", children: _jsx(Icon, { name: icon }) }) }));
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ContentIndicator } from './ContentIndicator.js';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { IconName } from '../../icons/registry';
|
|
2
|
+
import type { Size } from '../../types';
|
|
3
|
+
export type { Size };
|
|
4
|
+
/**
|
|
5
|
+
* Visual theme for the indicator.
|
|
6
|
+
* - `default`: Uses border color (neutral)
|
|
7
|
+
* - `info`: Blue theme
|
|
8
|
+
* - `success`: Green theme
|
|
9
|
+
* - `warning`: Amber theme
|
|
10
|
+
* - `danger`: Red theme
|
|
11
|
+
*/
|
|
12
|
+
export type Theme = 'default' | 'info' | 'success' | 'warning' | 'danger';
|
|
13
|
+
/**
|
|
14
|
+
* Visual variant.
|
|
15
|
+
* - `ring`: Hollow circle with border (default)
|
|
16
|
+
* - `solid`: Filled circle
|
|
17
|
+
*/
|
|
18
|
+
export type Variant = 'ring' | 'solid';
|
|
19
|
+
export type ContentIndicatorProps = {
|
|
20
|
+
/**
|
|
21
|
+
* Icon to display in the center.
|
|
22
|
+
* Uses the icon registry path format: "category/name"
|
|
23
|
+
* @example "lms/question-mark"
|
|
24
|
+
*/
|
|
25
|
+
icon: IconName;
|
|
26
|
+
/**
|
|
27
|
+
* Size of the indicator.
|
|
28
|
+
* - `'xs'`: 16px circle
|
|
29
|
+
* - `'sm'`: 24px circle (default)
|
|
30
|
+
* - `'md'`: 32px circle
|
|
31
|
+
* - `'lg'`: 40px circle
|
|
32
|
+
* @default 'sm'
|
|
33
|
+
*/
|
|
34
|
+
size?: Size;
|
|
35
|
+
/**
|
|
36
|
+
* Color theme for the indicator.
|
|
37
|
+
* @default 'default'
|
|
38
|
+
*/
|
|
39
|
+
theme?: Theme;
|
|
40
|
+
/**
|
|
41
|
+
* Visual variant.
|
|
42
|
+
* - `'ring'`: Hollow circle with border (default)
|
|
43
|
+
* - `'solid'`: Filled circle with icon in contrasting color
|
|
44
|
+
* @default 'ring'
|
|
45
|
+
*/
|
|
46
|
+
variant?: Variant;
|
|
47
|
+
/**
|
|
48
|
+
* Accessible label for the indicator.
|
|
49
|
+
* Required for meaningful icons. Omit only if the icon is purely decorative
|
|
50
|
+
* and context is provided by surrounding content.
|
|
51
|
+
*/
|
|
52
|
+
label?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Additional CSS class names.
|
|
55
|
+
*/
|
|
56
|
+
className?: string;
|
|
57
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DropdownProps, DropdownTriggerProps, DropdownContentProps, DropdownItemProps } from './types';
|
|
2
|
+
declare function DropdownRoot({ open: controlledOpen, onOpenChange, defaultOpen, children, }: DropdownProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
declare namespace DropdownRoot {
|
|
4
|
+
var displayName: string;
|
|
5
|
+
}
|
|
6
|
+
declare function DropdownTriggerComponent({ asChild, children }: DropdownTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare namespace DropdownTriggerComponent {
|
|
8
|
+
var displayName: string;
|
|
9
|
+
}
|
|
10
|
+
declare function DropdownContentComponent({ side, align, sideOffset, className, style, children, }: DropdownContentProps): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
declare namespace DropdownContentComponent {
|
|
12
|
+
var displayName: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Dropdown menu item. Renders a Button internally with ghost variant.
|
|
16
|
+
* When href is provided, renders as an anchor.
|
|
17
|
+
*/
|
|
18
|
+
declare function DropdownItemComponent({ onSelect, href, target, disabled, keepOpen, className, children, ...props }: DropdownItemProps & Record<string, unknown>): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
declare namespace DropdownItemComponent {
|
|
20
|
+
var displayName: string;
|
|
21
|
+
}
|
|
22
|
+
type DropdownCompound = typeof DropdownRoot & {
|
|
23
|
+
Trigger: typeof DropdownTriggerComponent;
|
|
24
|
+
Content: typeof DropdownContentComponent;
|
|
25
|
+
Item: typeof DropdownItemComponent;
|
|
26
|
+
};
|
|
27
|
+
export declare const Dropdown: DropdownCompound;
|
|
28
|
+
export declare const DropdownTrigger: typeof DropdownTriggerComponent;
|
|
29
|
+
export declare const DropdownContent: typeof DropdownContentComponent;
|
|
30
|
+
export declare const DropdownItem: typeof DropdownItemComponent;
|
|
31
|
+
export { useDropdownContext as useDropdown } from './DropdownContext';
|