@vinhhypc/config-theme 0.1.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/README.md +57 -0
- package/dist/components/themed/Accordion.d.ts +23 -0
- package/dist/components/themed/Accordion.js +37 -0
- package/dist/components/themed/Accordion.js.map +1 -0
- package/dist/components/themed/Alert.d.ts +13 -0
- package/dist/components/themed/Alert.js +17 -0
- package/dist/components/themed/Alert.js.map +1 -0
- package/dist/components/themed/Avatar.d.ts +19 -0
- package/dist/components/themed/Avatar.js +30 -0
- package/dist/components/themed/Avatar.js.map +1 -0
- package/dist/components/themed/Badge.d.ts +11 -0
- package/dist/components/themed/Badge.js +17 -0
- package/dist/components/themed/Badge.js.map +1 -0
- package/dist/components/themed/Button.d.ts +14 -0
- package/dist/components/themed/Button.js +20 -0
- package/dist/components/themed/Button.js.map +1 -0
- package/dist/components/themed/Calendar.d.ts +18 -0
- package/dist/components/themed/Calendar.js +59 -0
- package/dist/components/themed/Calendar.js.map +1 -0
- package/dist/components/themed/Card.d.ts +17 -0
- package/dist/components/themed/Card.js +14 -0
- package/dist/components/themed/Card.js.map +1 -0
- package/dist/components/themed/Checkbox.d.ts +16 -0
- package/dist/components/themed/Checkbox.js +15 -0
- package/dist/components/themed/Checkbox.js.map +1 -0
- package/dist/components/themed/DropdownMenu.d.ts +20 -0
- package/dist/components/themed/DropdownMenu.js +39 -0
- package/dist/components/themed/DropdownMenu.js.map +1 -0
- package/dist/components/themed/Input.d.ts +18 -0
- package/dist/components/themed/Input.js +25 -0
- package/dist/components/themed/Input.js.map +1 -0
- package/dist/components/themed/Pagination.d.ts +17 -0
- package/dist/components/themed/Pagination.js +33 -0
- package/dist/components/themed/Pagination.js.map +1 -0
- package/dist/components/themed/Select.d.ts +16 -0
- package/dist/components/themed/Select.js +20 -0
- package/dist/components/themed/Select.js.map +1 -0
- package/dist/components/themed/Sheet.d.ts +19 -0
- package/dist/components/themed/Sheet.js +28 -0
- package/dist/components/themed/Sheet.js.map +1 -0
- package/dist/components/themed/Sidebar.d.ts +21 -0
- package/dist/components/themed/Sidebar.js +11 -0
- package/dist/components/themed/Sidebar.js.map +1 -0
- package/dist/components/themed/Table.d.ts +21 -0
- package/dist/components/themed/Table.js +10 -0
- package/dist/components/themed/Table.js.map +1 -0
- package/dist/components/themed/ThemeProvider.d.ts +41 -0
- package/dist/components/themed/ThemeProvider.js +53 -0
- package/dist/components/themed/ThemeProvider.js.map +1 -0
- package/dist/components/themed/Toast.d.ts +19 -0
- package/dist/components/themed/Toast.js +13 -0
- package/dist/components/themed/Toast.js.map +1 -0
- package/dist/components/themed/Tooltip.d.ts +15 -0
- package/dist/components/themed/Tooltip.js +11 -0
- package/dist/components/themed/Tooltip.js.map +1 -0
- package/dist/components/themed/index.d.ts +33 -0
- package/dist/components/themed/index.js +35 -0
- package/dist/components/themed/index.js.map +1 -0
- package/dist/components/themed/styles.d.ts +29 -0
- package/dist/components/themed/styles.js +270 -0
- package/dist/components/themed/styles.js.map +1 -0
- package/dist/components/themed/themeCss.d.ts +35 -0
- package/dist/components/themed/themeCss.js +76 -0
- package/dist/components/themed/themeCss.js.map +1 -0
- package/dist/lib/config/defaults.d.ts +5 -0
- package/dist/lib/config/defaults.js +86 -0
- package/dist/lib/config/defaults.js.map +1 -0
- package/dist/lib/config/presets.d.ts +13 -0
- package/dist/lib/config/presets.js +104 -0
- package/dist/lib/config/presets.js.map +1 -0
- package/dist/lib/config/types.d.ts +146 -0
- package/dist/lib/config/types.js +46 -0
- package/dist/lib/config/types.js.map +1 -0
- package/dist/lib/tokens/adapters.d.ts +15 -0
- package/dist/lib/tokens/adapters.js +102 -0
- package/dist/lib/tokens/adapters.js.map +1 -0
- package/dist/lib/tokens/color.d.ts +23 -0
- package/dist/lib/tokens/color.js +132 -0
- package/dist/lib/tokens/color.js.map +1 -0
- package/dist/lib/tokens/elevation.d.ts +6 -0
- package/dist/lib/tokens/elevation.js +40 -0
- package/dist/lib/tokens/elevation.js.map +1 -0
- package/dist/lib/tokens/index.d.ts +43 -0
- package/dist/lib/tokens/index.js +88 -0
- package/dist/lib/tokens/index.js.map +1 -0
- package/dist/lib/tokens/interactions.d.ts +12 -0
- package/dist/lib/tokens/interactions.js +72 -0
- package/dist/lib/tokens/interactions.js.map +1 -0
- package/dist/lib/tokens/opacity.d.ts +14 -0
- package/dist/lib/tokens/opacity.js +34 -0
- package/dist/lib/tokens/opacity.js.map +1 -0
- package/dist/lib/tokens/spacing.d.ts +17 -0
- package/dist/lib/tokens/spacing.js +32 -0
- package/dist/lib/tokens/spacing.js.map +1 -0
- package/dist/lib/tokens/typography.d.ts +16 -0
- package/dist/lib/tokens/typography.js +23 -0
- package/dist/lib/tokens/typography.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @vinhhypc/config-theme
|
|
2
|
+
|
|
3
|
+
Token-driven React components. Every component is styled by a `<ThemeProvider>`
|
|
4
|
+
that receives a `DesignConfig` (your chosen design tokens) and injects the CSS
|
|
5
|
+
variables + stylesheet — so the whole tree re-themes from one config.
|
|
6
|
+
|
|
7
|
+
📖 **Live docs / playground:** https://storybook-config-theme.vercel.app
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i @vinhhypc/config-theme react react-dom
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
Wrap your app (or any subtree) in `<ThemeProvider>` and use any component.
|
|
18
|
+
You import only what you need — unused components are tree-shaken out.
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { ThemeProvider, Button, Card, applyPreset } from "@vinhhypc/config-theme";
|
|
22
|
+
|
|
23
|
+
// Tokens: a built-in preset, or your own DesignConfig (e.g. saved JSON).
|
|
24
|
+
const config = applyPreset("modern");
|
|
25
|
+
|
|
26
|
+
export default function App() {
|
|
27
|
+
return (
|
|
28
|
+
<ThemeProvider config={config} mode="light">
|
|
29
|
+
<Card title="Hello" footer={<Button>OK</Button>}>
|
|
30
|
+
This card themes itself from the config.
|
|
31
|
+
</Card>
|
|
32
|
+
</ThemeProvider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`<ThemeProvider>` is required — without it components render unstyled.
|
|
38
|
+
|
|
39
|
+
## Components
|
|
40
|
+
|
|
41
|
+
`Accordion`, `Alert`, `Avatar`, `Badge`, `Button`, `Calendar`, `Card`,
|
|
42
|
+
`Checkbox`, `DropdownMenu`, `Input` / `Field`, `Pagination`, `Select`,
|
|
43
|
+
`Sheet`, `Sidebar`, `Table`, `Toast`, `Tooltip`.
|
|
44
|
+
|
|
45
|
+
Also exported: `useTheme()`, the token layer (`presets`, `applyPreset`,
|
|
46
|
+
`defaultConfig`, `resolveTokens`) and the `DesignConfig` type.
|
|
47
|
+
|
|
48
|
+
## Notes
|
|
49
|
+
|
|
50
|
+
- **Fonts**: the tokens only declare `font-family`. Load the matching web fonts
|
|
51
|
+
yourself (e.g. Google Fonts / `next/font`).
|
|
52
|
+
- **Next.js App Router**: components are client components (the published bundle
|
|
53
|
+
carries the `"use client"` directive).
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
export interface AccordionItem {
|
|
3
|
+
id: string;
|
|
4
|
+
title: ReactNode;
|
|
5
|
+
content: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export interface AccordionProps {
|
|
8
|
+
items: AccordionItem[];
|
|
9
|
+
/** Allow multiple panels open at once. Default: single (closes others). */
|
|
10
|
+
multiple?: boolean;
|
|
11
|
+
/** Ids of panels open initially. */
|
|
12
|
+
defaultOpen?: string[];
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Token-driven accordion. Emits semantic classes (`tc-accordion`, …) styled by
|
|
17
|
+
* the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
18
|
+
* config. Open state is managed internally.
|
|
19
|
+
*/
|
|
20
|
+
export declare function Accordion({ items, multiple, defaultOpen, className, }: AccordionProps): React.JSX.Element;
|
|
21
|
+
export declare namespace Accordion {
|
|
22
|
+
var displayName: string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
4
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
/** Caret icon, rotated via CSS when its item is open. */
|
|
7
|
+
function Caret() {
|
|
8
|
+
return (_jsx("svg", { className: "tc-accordion__icon", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Token-driven accordion. Emits semantic classes (`tc-accordion`, …) styled by
|
|
12
|
+
* the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
13
|
+
* config. Open state is managed internally.
|
|
14
|
+
*/
|
|
15
|
+
export function Accordion({ items, multiple = false, defaultOpen = [], className, }) {
|
|
16
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
17
|
+
const toggle = (id) => {
|
|
18
|
+
setOpen((prev) => {
|
|
19
|
+
const isOpen = prev.includes(id);
|
|
20
|
+
if (multiple) {
|
|
21
|
+
return isOpen ? prev.filter((x) => x !== id) : [...prev, id];
|
|
22
|
+
}
|
|
23
|
+
return isOpen ? [] : [id];
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const classes = ["tc-accordion"];
|
|
27
|
+
if (className)
|
|
28
|
+
classes.push(className);
|
|
29
|
+
return (_jsx("div", { className: classes.join(" "), children: items.map((item) => {
|
|
30
|
+
const isOpen = open.includes(item.id);
|
|
31
|
+
const panelId = `tc-acc-panel-${item.id}`;
|
|
32
|
+
const headerId = `tc-acc-header-${item.id}`;
|
|
33
|
+
return (_jsxs("div", { className: "tc-accordion__item", "data-open": isOpen, children: [_jsxs("button", { type: "button", id: headerId, className: "tc-accordion__header", "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => toggle(item.id), children: [_jsx("span", { children: item.title }), _jsx(Caret, {})] }), isOpen && (_jsx("div", { id: panelId, role: "region", "aria-labelledby": headerId, className: "tc-accordion__panel", children: item.content }))] }, item.id));
|
|
34
|
+
}) }));
|
|
35
|
+
}
|
|
36
|
+
Accordion.displayName = "Accordion";
|
|
37
|
+
//# sourceMappingURL=Accordion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Accordion.js","sourceRoot":"","sources":["../../../../../components/themed/Accordion.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAiBxD,yDAAyD;AACzD,SAAS,KAAK;IACZ,OAAO,CACL,cAAK,SAAS,EAAC,oBAAoB,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,iBAAa,MAAM,YACpF,eACE,CAAC,EAAC,cAAc,EAChB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GACtB,GACE,CACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,EAAE,EAChB,SAAS,GACM;IACf,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAW,WAAW,CAAC,CAAC;IAExD,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAE;QAC5B,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACf,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,cAAc,CAAC,CAAC;IACjC,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEvC,OAAO,CACL,cAAK,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,YAC9B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAClB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,gBAAgB,IAAI,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,iBAAiB,IAAI,CAAC,EAAE,EAAE,CAAC;YAC5C,OAAO,CACL,eAAmB,SAAS,EAAC,oBAAoB,eAAY,MAAM,aACjE,kBACE,IAAI,EAAC,QAAQ,EACb,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAC,sBAAsB,mBACjB,MAAM,mBACN,OAAO,EACtB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,aAE9B,yBAAO,IAAI,CAAC,KAAK,GAAQ,EACzB,KAAC,KAAK,KAAG,IACF,EACR,MAAM,IAAI,CACT,cAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAC,QAAQ,qBAAkB,QAAQ,EAAE,SAAS,EAAC,qBAAqB,YACvF,IAAI,CAAC,OAAO,GACT,CACP,KAhBO,IAAI,CAAC,EAAE,CAiBX,CACP,CAAC;QACJ,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC;AAED,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React, { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export type AlertVariant = "success" | "warning" | "error" | "info";
|
|
3
|
+
export interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
4
|
+
variant?: AlertVariant;
|
|
5
|
+
/** Optional bold title rendered above the body. */
|
|
6
|
+
title?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Token-driven alert. Emits semantic classes (`tc-alert`, `tc-alert--info`, …)
|
|
10
|
+
* styled by the surrounding `<ThemedSurface>`, so it re-themes with the active
|
|
11
|
+
* design config.
|
|
12
|
+
*/
|
|
13
|
+
export declare const Alert: React.ForwardRefExoticComponent<AlertProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
3
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Token-driven alert. Emits semantic classes (`tc-alert`, `tc-alert--info`, …)
|
|
7
|
+
* styled by the surrounding `<ThemedSurface>`, so it re-themes with the active
|
|
8
|
+
* design config.
|
|
9
|
+
*/
|
|
10
|
+
export const Alert = forwardRef(({ variant = "info", title, className, children, ...props }, ref) => {
|
|
11
|
+
const classes = ["tc-alert", `tc-alert--${variant}`];
|
|
12
|
+
if (className)
|
|
13
|
+
classes.push(className);
|
|
14
|
+
return (_jsxs("div", { ref: ref, role: "alert", className: classes.join(" "), ...props, children: [title != null && _jsx("div", { className: "tc-alert__title", children: title }), children != null && _jsx("div", { className: "tc-alert__body", children: children })] }));
|
|
15
|
+
});
|
|
16
|
+
Alert.displayName = "Alert";
|
|
17
|
+
//# sourceMappingURL=Alert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.js","sourceRoot":"","sources":["../../../../../components/themed/Alert.tsx"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,UAAU,EAAuC,MAAM,OAAO,CAAC;AAU/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAC7B,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAClE,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,aAAa,OAAO,EAAE,CAAC,CAAC;IACrD,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,CACL,eAAK,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC,OAAO,EAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAM,KAAK,aAChE,KAAK,IAAI,IAAI,IAAI,cAAK,SAAS,EAAC,iBAAiB,YAAE,KAAK,GAAO,EAC/D,QAAQ,IAAI,IAAI,IAAI,cAAK,SAAS,EAAC,gBAAgB,YAAE,QAAQ,GAAO,IACjE,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React, { type HTMLAttributes } from "react";
|
|
2
|
+
export type AvatarSize = "sm" | "md" | "lg";
|
|
3
|
+
export type AvatarVariant = "primary" | "accent" | "soft";
|
|
4
|
+
export interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
|
+
size?: AvatarSize;
|
|
6
|
+
variant?: AvatarVariant;
|
|
7
|
+
/** Image source. When set, the image fills the avatar; otherwise initials show. */
|
|
8
|
+
src?: string;
|
|
9
|
+
/** Accessible alt / image description (also used as the title). */
|
|
10
|
+
alt?: string;
|
|
11
|
+
/** Initials / fallback content shown when no `src` is provided. */
|
|
12
|
+
name?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Token-driven avatar. Emits semantic classes (`tc-avatar`, `tc-avatar--lg`,
|
|
16
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
17
|
+
* active design config. Renders an image when `src` is set, else initials.
|
|
18
|
+
*/
|
|
19
|
+
export declare const Avatar: React.ForwardRefExoticComponent<AvatarProps & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
3
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
/** Derive up to two uppercase initials from a name. */
|
|
6
|
+
function initials(name) {
|
|
7
|
+
if (!name)
|
|
8
|
+
return "";
|
|
9
|
+
const parts = name.trim().split(/\s+/).slice(0, 2);
|
|
10
|
+
return parts.map((p) => p[0]?.toUpperCase() ?? "").join("");
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Token-driven avatar. Emits semantic classes (`tc-avatar`, `tc-avatar--lg`,
|
|
14
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
15
|
+
* active design config. Renders an image when `src` is set, else initials.
|
|
16
|
+
*/
|
|
17
|
+
export const Avatar = forwardRef(({ size = "md", variant = "primary", src, alt, name, className, children, ...props }, ref) => {
|
|
18
|
+
const classes = ["tc-avatar"];
|
|
19
|
+
if (size !== "md")
|
|
20
|
+
classes.push(`tc-avatar--${size}`);
|
|
21
|
+
if (variant !== "primary")
|
|
22
|
+
classes.push(`tc-avatar--${variant}`);
|
|
23
|
+
if (className)
|
|
24
|
+
classes.push(className);
|
|
25
|
+
return (_jsx("span", { ref: ref, className: classes.join(" "), title: alt ?? name, ...props, children: src ? (
|
|
26
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
27
|
+
_jsx("img", { src: src, alt: alt ?? name ?? "" })) : (children ?? initials(name)) }));
|
|
28
|
+
});
|
|
29
|
+
Avatar.displayName = "Avatar";
|
|
30
|
+
//# sourceMappingURL=Avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../../../components/themed/Avatar.tsx"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,UAAU,EAAuB,MAAM,OAAO,CAAC;AAgB/D,uDAAuD;AACvD,SAAS,QAAQ,CAAC,IAAa;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAC9B,CAAC,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,GAAG,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAC3F,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACtD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;IACjE,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,CACL,eAAM,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,IAAI,IAAI,KAAM,KAAK,YACxE,GAAG,CAAC,CAAC,CAAC;QACL,qDAAqD;QACrD,cAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,IAAI,IAAI,EAAE,GAAI,CAC1C,CAAC,CAAC,CAAC,CACF,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,CAC3B,GACI,CACR,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React, { type HTMLAttributes } from "react";
|
|
2
|
+
export type BadgeVariant = "solid" | "neutral" | "success" | "warning" | "error" | "info";
|
|
3
|
+
export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
+
variant?: BadgeVariant;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Token-driven badge. Emits semantic classes (`tc-badge`, `tc-badge--success`,
|
|
8
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
9
|
+
* active design config.
|
|
10
|
+
*/
|
|
11
|
+
export declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
3
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Token-driven badge. Emits semantic classes (`tc-badge`, `tc-badge--success`,
|
|
7
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
8
|
+
* active design config.
|
|
9
|
+
*/
|
|
10
|
+
export const Badge = forwardRef(({ variant = "solid", className, ...props }, ref) => {
|
|
11
|
+
const classes = ["tc-badge", `tc-badge--${variant}`];
|
|
12
|
+
if (className)
|
|
13
|
+
classes.push(className);
|
|
14
|
+
return _jsx("span", { ref: ref, className: classes.join(" "), ...props });
|
|
15
|
+
});
|
|
16
|
+
Badge.displayName = "Badge";
|
|
17
|
+
//# sourceMappingURL=Badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../../../components/themed/Badge.tsx"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,UAAU,EAAuB,MAAM,OAAO,CAAC;AAc/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAC7B,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAClD,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,aAAa,OAAO,EAAE,CAAC,CAAC;IACrD,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,eAAM,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAM,KAAK,GAAI,CAAC;AACrE,CAAC,CACF,CAAC;AAEF,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React, { type ButtonHTMLAttributes } from "react";
|
|
2
|
+
export type ButtonVariant = "primary" | "secondary" | "ghost" | "outline" | "destructive";
|
|
3
|
+
export type ButtonSize = "sm" | "md" | "lg";
|
|
4
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
size?: ButtonSize;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Token-driven button. Carries no colours/spacing of its own — it only emits
|
|
10
|
+
* semantic classes (`tcb`, `tcb--primary`, …) whose visual style comes from the
|
|
11
|
+
* surrounding `<ThemedSurface>` for the active design config. The same button
|
|
12
|
+
* therefore re-themes automatically when the config changes.
|
|
13
|
+
*/
|
|
14
|
+
export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
3
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Token-driven button. Carries no colours/spacing of its own — it only emits
|
|
7
|
+
* semantic classes (`tcb`, `tcb--primary`, …) whose visual style comes from the
|
|
8
|
+
* surrounding `<ThemedSurface>` for the active design config. The same button
|
|
9
|
+
* therefore re-themes automatically when the config changes.
|
|
10
|
+
*/
|
|
11
|
+
export const Button = forwardRef(({ variant = "primary", size = "md", className, type = "button", ...props }, ref) => {
|
|
12
|
+
const classes = ["tcb", `tcb--${variant}`];
|
|
13
|
+
if (size !== "md")
|
|
14
|
+
classes.push(`tcb--${size}`);
|
|
15
|
+
if (className)
|
|
16
|
+
classes.push(className);
|
|
17
|
+
return _jsx("button", { ref: ref, type: type, className: classes.join(" "), ...props });
|
|
18
|
+
});
|
|
19
|
+
Button.displayName = "Button";
|
|
20
|
+
//# sourceMappingURL=Button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../components/themed/Button.tsx"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,UAAU,EAA6B,MAAM,OAAO,CAAC;AAgBrE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAC9B,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAClF,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,OAAO,EAAE,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,iBAAQ,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAM,KAAK,GAAI,CAAC;AACnF,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface CalendarProps {
|
|
3
|
+
/** Currently selected date (controlled). */
|
|
4
|
+
value?: Date;
|
|
5
|
+
/** Fired when a day is clicked. */
|
|
6
|
+
onChange?: (date: Date) => void;
|
|
7
|
+
/** Month to display initially (defaults to today, or `value`'s month). */
|
|
8
|
+
defaultMonth?: Date;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Token-driven month calendar. Emits semantic classes (`tc-cal`, …) styled by
|
|
12
|
+
* the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
13
|
+
* config. Selection/month navigation is managed internally.
|
|
14
|
+
*/
|
|
15
|
+
export declare function Calendar({ value, onChange, defaultMonth }: CalendarProps): React.JSX.Element;
|
|
16
|
+
export declare namespace Calendar {
|
|
17
|
+
var displayName: string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
4
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
5
|
+
import { useMemo, useState } from "react";
|
|
6
|
+
const DOW = ["T2", "T3", "T4", "T5", "T6", "T7", "CN"]; // Monday-first
|
|
7
|
+
const MONTHS = [
|
|
8
|
+
"Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6",
|
|
9
|
+
"Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12",
|
|
10
|
+
];
|
|
11
|
+
const sameDay = (a, b) => a.getFullYear() === b.getFullYear() &&
|
|
12
|
+
a.getMonth() === b.getMonth() &&
|
|
13
|
+
a.getDate() === b.getDate();
|
|
14
|
+
/** Days to render for a month grid, padded to whole weeks (Monday-first). */
|
|
15
|
+
function buildGrid(year, month) {
|
|
16
|
+
const first = new Date(year, month, 1);
|
|
17
|
+
// JS getDay(): 0=Sun … 6=Sat. Convert to Monday-first offset (0=Mon … 6=Sun).
|
|
18
|
+
const lead = (first.getDay() + 6) % 7;
|
|
19
|
+
const start = new Date(year, month, 1 - lead);
|
|
20
|
+
return Array.from({ length: 42 }, (_, i) => {
|
|
21
|
+
const d = new Date(start);
|
|
22
|
+
d.setDate(start.getDate() + i);
|
|
23
|
+
return d;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Token-driven month calendar. Emits semantic classes (`tc-cal`, …) styled by
|
|
28
|
+
* the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
29
|
+
* config. Selection/month navigation is managed internally.
|
|
30
|
+
*/
|
|
31
|
+
export function Calendar({ value, onChange, defaultMonth }) {
|
|
32
|
+
const today = useMemo(() => new Date(), []);
|
|
33
|
+
const initial = defaultMonth ?? value ?? today;
|
|
34
|
+
const [view, setView] = useState({ y: initial.getFullYear(), m: initial.getMonth() });
|
|
35
|
+
const [internal, setInternal] = useState(value);
|
|
36
|
+
const selected = value ?? internal;
|
|
37
|
+
const days = useMemo(() => buildGrid(view.y, view.m), [view]);
|
|
38
|
+
const shift = (delta) => {
|
|
39
|
+
const d = new Date(view.y, view.m + delta, 1);
|
|
40
|
+
setView({ y: d.getFullYear(), m: d.getMonth() });
|
|
41
|
+
};
|
|
42
|
+
const pick = (d) => {
|
|
43
|
+
setInternal(d);
|
|
44
|
+
onChange?.(d);
|
|
45
|
+
};
|
|
46
|
+
return (_jsxs("div", { className: "tc-cal", children: [_jsxs("div", { className: "tc-cal__head", children: [_jsx("button", { type: "button", className: "tc-cal__nav", "aria-label": "Th\u00E1ng tr\u01B0\u1EDBc", onClick: () => shift(-1), children: "\u2039" }), _jsxs("span", { className: "tc-cal__title", children: [MONTHS[view.m], " ", view.y] }), _jsx("button", { type: "button", className: "tc-cal__nav", "aria-label": "Th\u00E1ng sau", onClick: () => shift(1), children: "\u203A" })] }), _jsxs("div", { className: "tc-cal__grid", children: [DOW.map((d) => (_jsx("div", { className: "tc-cal__dow", children: d }, d))), days.map((d) => {
|
|
47
|
+
const muted = d.getMonth() !== view.m;
|
|
48
|
+
const classes = ["tc-cal__day"];
|
|
49
|
+
if (muted)
|
|
50
|
+
classes.push("tc-cal__day--muted");
|
|
51
|
+
if (sameDay(d, today))
|
|
52
|
+
classes.push("tc-cal__day--today");
|
|
53
|
+
if (selected && sameDay(d, selected))
|
|
54
|
+
classes.push("tc-cal__day--selected");
|
|
55
|
+
return (_jsx("button", { type: "button", className: classes.join(" "), "aria-pressed": selected ? sameDay(d, selected) : false, onClick: () => pick(d), children: d.getDate() }, d.toISOString()));
|
|
56
|
+
})] })] }));
|
|
57
|
+
}
|
|
58
|
+
Calendar.displayName = "Calendar";
|
|
59
|
+
//# sourceMappingURL=Calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calendar.js","sourceRoot":"","sources":["../../../../../components/themed/Calendar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export type CardVariant = "elevated" | "outlined" | "flat";
|
|
3
|
+
export interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
4
|
+
variant?: CardVariant;
|
|
5
|
+
title?: ReactNode;
|
|
6
|
+
/** Footer content (e.g. action buttons). */
|
|
7
|
+
footer?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Token-driven card. Emits semantic classes (`tc-card`, `tc-card--outlined`,
|
|
11
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
12
|
+
* active design config.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Card({ variant, title, footer, className, children, ...props }: CardProps): React.JSX.Element;
|
|
15
|
+
export declare namespace Card {
|
|
16
|
+
var displayName: string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Token-driven card. Emits semantic classes (`tc-card`, `tc-card--outlined`,
|
|
4
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
5
|
+
* active design config.
|
|
6
|
+
*/
|
|
7
|
+
export function Card({ variant = "elevated", title, footer, className, children, ...props }) {
|
|
8
|
+
const classes = ["tc-card", `tc-card--${variant}`];
|
|
9
|
+
if (className)
|
|
10
|
+
classes.push(className);
|
|
11
|
+
return (_jsxs("div", { className: classes.join(" "), ...props, children: [title != null && _jsx("h3", { className: "tc-card__title", children: title }), children != null && _jsx("div", { className: "tc-card__body", children: children }), footer != null && _jsx("div", { className: "tc-card__foot", children: footer })] }));
|
|
12
|
+
}
|
|
13
|
+
Card.displayName = "Card";
|
|
14
|
+
//# sourceMappingURL=Card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.js","sourceRoot":"","sources":["../../../../../components/themed/Card.tsx"],"names":[],"mappings":";AAaA;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAa;IACpG,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,YAAY,OAAO,EAAE,CAAC,CAAC;IACnD,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAM,KAAK,aACzC,KAAK,IAAI,IAAI,IAAI,aAAI,SAAS,EAAC,gBAAgB,YAAE,KAAK,GAAM,EAC5D,QAAQ,IAAI,IAAI,IAAI,cAAK,SAAS,EAAC,eAAe,YAAE,QAAQ,GAAO,EACnE,MAAM,IAAI,IAAI,IAAI,cAAK,SAAS,EAAC,eAAe,YAAE,MAAM,GAAO,IAC5D,CACP,CAAC;AACJ,CAAC;AAED,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
export interface CheckboxProps {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
onCheckedChange: (checked: boolean) => void;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Token-driven checkbox. Emits semantic classes (`tc-checkbox`, …) styled by
|
|
10
|
+
* the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
11
|
+
* config. The native input is visually hidden but keeps keyboard/a11y support.
|
|
12
|
+
*/
|
|
13
|
+
export declare function Checkbox({ checked, onCheckedChange, disabled, children }: CheckboxProps): React.JSX.Element;
|
|
14
|
+
export declare namespace Checkbox {
|
|
15
|
+
var displayName: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Tick icon shown when checked (revealed via CSS). */
|
|
3
|
+
function Tick() {
|
|
4
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Token-driven checkbox. Emits semantic classes (`tc-checkbox`, …) styled by
|
|
8
|
+
* the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
9
|
+
* config. The native input is visually hidden but keeps keyboard/a11y support.
|
|
10
|
+
*/
|
|
11
|
+
export function Checkbox({ checked, onCheckedChange, disabled, children }) {
|
|
12
|
+
return (_jsxs("label", { className: "tc-checkbox", "data-checked": checked, "data-disabled": disabled, children: [_jsx("input", { type: "checkbox", checked: checked, disabled: disabled, onChange: (e) => onCheckedChange(e.target.checked) }), _jsx("span", { className: "tc-checkbox__box", children: _jsx(Tick, {}) }), children] }));
|
|
13
|
+
}
|
|
14
|
+
Checkbox.displayName = "Checkbox";
|
|
15
|
+
//# sourceMappingURL=Checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../../../../components/themed/Checkbox.tsx"],"names":[],"mappings":";AAWA,uDAAuD;AACvD,SAAS,IAAI;IACX,OAAO,CACL,cAAK,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,iBAAa,MAAM,YACrD,eACE,CAAC,EAAC,kBAAkB,EACpB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GACtB,GACE,CACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAiB;IACtF,OAAO,CACL,iBAAO,SAAS,EAAC,aAAa,kBAAe,OAAO,mBAAiB,QAAQ,aAC3E,gBACE,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAClD,EACF,eAAM,SAAS,EAAC,kBAAkB,YAChC,KAAC,IAAI,KAAG,GACH,EACN,QAAQ,IACH,CACT,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
export interface DropdownMenuItem {
|
|
3
|
+
id: string;
|
|
4
|
+
label: ReactNode;
|
|
5
|
+
onSelect?: () => void;
|
|
6
|
+
}
|
|
7
|
+
export interface DropdownMenuProps {
|
|
8
|
+
/** Trigger button label. */
|
|
9
|
+
trigger: ReactNode;
|
|
10
|
+
items: DropdownMenuItem[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Token-driven dropdown menu. Emits semantic classes (`tc-dropdown`, …) styled
|
|
14
|
+
* by the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
15
|
+
* config. Closes on outside-click / Escape.
|
|
16
|
+
*/
|
|
17
|
+
export declare function DropdownMenu({ trigger, items }: DropdownMenuProps): React.JSX.Element;
|
|
18
|
+
export declare namespace DropdownMenu {
|
|
19
|
+
var displayName: string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
4
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
5
|
+
import { useEffect, useRef, useState } from "react";
|
|
6
|
+
import { Button } from "./Button.js";
|
|
7
|
+
/**
|
|
8
|
+
* Token-driven dropdown menu. Emits semantic classes (`tc-dropdown`, …) styled
|
|
9
|
+
* by the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
10
|
+
* config. Closes on outside-click / Escape.
|
|
11
|
+
*/
|
|
12
|
+
export function DropdownMenu({ trigger, items }) {
|
|
13
|
+
const [open, setOpen] = useState(false);
|
|
14
|
+
const ref = useRef(null);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!open)
|
|
17
|
+
return;
|
|
18
|
+
const onDocClick = (e) => {
|
|
19
|
+
if (ref.current && !ref.current.contains(e.target))
|
|
20
|
+
setOpen(false);
|
|
21
|
+
};
|
|
22
|
+
const onKey = (e) => {
|
|
23
|
+
if (e.key === "Escape")
|
|
24
|
+
setOpen(false);
|
|
25
|
+
};
|
|
26
|
+
document.addEventListener("mousedown", onDocClick);
|
|
27
|
+
document.addEventListener("keydown", onKey);
|
|
28
|
+
return () => {
|
|
29
|
+
document.removeEventListener("mousedown", onDocClick);
|
|
30
|
+
document.removeEventListener("keydown", onKey);
|
|
31
|
+
};
|
|
32
|
+
}, [open]);
|
|
33
|
+
return (_jsxs("div", { className: "tc-dropdown", ref: ref, children: [_jsx(Button, { variant: "outline", "aria-haspopup": "menu", "aria-expanded": open, onClick: () => setOpen((o) => !o), children: trigger }), open && (_jsx("div", { className: "tc-dropdown__menu", role: "menu", children: items.map((item) => (_jsx("button", { type: "button", role: "menuitem", className: "tc-dropdown__item", onClick: () => {
|
|
34
|
+
item.onSelect?.();
|
|
35
|
+
setOpen(false);
|
|
36
|
+
}, children: item.label }, item.id))) }))] }));
|
|
37
|
+
}
|
|
38
|
+
DropdownMenu.displayName = "DropdownMenu";
|
|
39
|
+
//# sourceMappingURL=DropdownMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../../../components/themed/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAclC;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAqB;IAChE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,UAAU,GAAG,CAAC,CAAa,EAAE,EAAE;YACnC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC;gBAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7E,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,CAAgB,EAAE,EAAE;YACjC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;gBAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACnD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC5C,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YACtD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,eAAK,SAAS,EAAC,aAAa,EAAC,GAAG,EAAE,GAAG,aACnC,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,mBAAe,MAAM,mBAAgB,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAClG,OAAO,GACD,EACR,IAAI,IAAI,CACP,cAAK,SAAS,EAAC,mBAAmB,EAAC,IAAI,EAAC,MAAM,YAC3C,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,iBAEE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,UAAU,EACf,SAAS,EAAC,mBAAmB,EAC7B,OAAO,EAAE,GAAG,EAAE;wBACZ,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;wBAClB,OAAO,CAAC,KAAK,CAAC,CAAC;oBACjB,CAAC,YAEA,IAAI,CAAC,KAAK,IATN,IAAI,CAAC,EAAE,CAUL,CACV,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED,YAAY,CAAC,WAAW,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { type InputHTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export type InputVariant = "outline" | "filled" | "underline";
|
|
3
|
+
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
4
|
+
variant?: InputVariant;
|
|
5
|
+
/** Renders the error styling. */
|
|
6
|
+
error?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Token-driven input. Emits semantic classes (`tci`, `tci--filled`, …) styled
|
|
10
|
+
* by the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
11
|
+
* config.
|
|
12
|
+
*/
|
|
13
|
+
export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
14
|
+
/** Labelled field wrapper using the themed `tc-field` styles. */
|
|
15
|
+
export declare function Field({ label, children, }: {
|
|
16
|
+
label: ReactNode;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// `React` imported explicitly so this also renders under Storybook's Vite
|
|
3
|
+
// pipeline (classic JSX runtime); harmless in the Next app.
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Token-driven input. Emits semantic classes (`tci`, `tci--filled`, …) styled
|
|
7
|
+
* by the surrounding `<ThemedSurface>`, so it re-themes with the active design
|
|
8
|
+
* config.
|
|
9
|
+
*/
|
|
10
|
+
export const Input = forwardRef(({ variant = "outline", error, className, ...props }, ref) => {
|
|
11
|
+
const classes = ["tci"];
|
|
12
|
+
if (variant !== "outline")
|
|
13
|
+
classes.push(`tci--${variant}`);
|
|
14
|
+
if (error)
|
|
15
|
+
classes.push("tci--error");
|
|
16
|
+
if (className)
|
|
17
|
+
classes.push(className);
|
|
18
|
+
return _jsx("input", { ref: ref, className: classes.join(" "), ...props });
|
|
19
|
+
});
|
|
20
|
+
Input.displayName = "Input";
|
|
21
|
+
/** Labelled field wrapper using the themed `tc-field` styles. */
|
|
22
|
+
export function Field({ label, children, }) {
|
|
23
|
+
return (_jsxs("label", { className: "tc-field", children: [_jsx("span", { children: label }), children] }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=Input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../../components/themed/Input.tsx"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,4DAA4D;AAC5D,OAAc,EAAE,UAAU,EAA4C,MAAM,OAAO,CAAC;AAUpF;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAC7B,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAC3D,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC;IAC3D,IAAI,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAM,KAAK,GAAI,CAAC;AACtE,CAAC,CACF,CAAC;AAEF,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC;AAE5B,iEAAiE;AACjE,MAAM,UAAU,KAAK,CAAC,EACpB,KAAK,EACL,QAAQ,GAIT;IACC,OAAO,CACL,iBAAO,SAAS,EAAC,UAAU,aACzB,yBAAO,KAAK,GAAQ,EACnB,QAAQ,IACH,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface PaginationProps {
|
|
3
|
+
page: number;
|
|
4
|
+
total: number;
|
|
5
|
+
onChange: (page: number) => void;
|
|
6
|
+
/** Max number of page buttons to show (excluding prev/next). */
|
|
7
|
+
siblings?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Token-driven pagination. Emits semantic classes (`tc-pagination`, `tc-page`,
|
|
11
|
+
* …) styled by the surrounding `<ThemedSurface>`, so it re-themes with the
|
|
12
|
+
* active design config.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Pagination({ page, total, onChange, siblings }: PaginationProps): React.JSX.Element;
|
|
15
|
+
export declare namespace Pagination {
|
|
16
|
+
var displayName: string;
|
|
17
|
+
}
|