@tribepad/themis 1.9.3 → 1.9.5
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/CHANGELOG.md +12 -0
- package/dist/elements/AlertDialog/index.js +1 -1
- package/dist/elements/AlertDialog/index.js.map +1 -1
- package/dist/elements/AlertDialog/index.mjs +1 -1
- package/dist/elements/AlertDialog/index.mjs.map +1 -1
- package/dist/elements/Breadcrumbs/index.js +1 -1
- package/dist/elements/Breadcrumbs/index.js.map +1 -1
- package/dist/elements/Breadcrumbs/index.mjs +1 -1
- package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
- package/dist/elements/Button/index.js +1 -1
- package/dist/elements/Button/index.js.map +1 -1
- package/dist/elements/Button/index.mjs +1 -1
- package/dist/elements/Button/index.mjs.map +1 -1
- package/dist/elements/Card/index.js +1 -1
- package/dist/elements/Card/index.js.map +1 -1
- package/dist/elements/Card/index.mjs +1 -1
- package/dist/elements/Card/index.mjs.map +1 -1
- package/dist/elements/Carousel/Carousel.d.ts +8 -1
- package/dist/elements/Carousel/Carousel.d.ts.map +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts.map +1 -1
- package/dist/elements/Carousel/index.js +1 -1
- package/dist/elements/Carousel/index.js.map +1 -1
- package/dist/elements/Carousel/index.mjs +1 -1
- package/dist/elements/Carousel/index.mjs.map +1 -1
- package/dist/elements/ChatInterface/ChatLiveRegions.d.ts +2 -2
- package/dist/elements/ChatInterface/ChatLiveRegions.d.ts.map +1 -1
- package/dist/elements/ChatInterface/ChatMessageBubble.d.ts +1 -1
- package/dist/elements/ChatInterface/ChatMessageBubble.d.ts.map +1 -1
- package/dist/elements/ChatInterface/ChatThinkingDisplay.d.ts +2 -2
- package/dist/elements/ChatInterface/ChatThinkingDisplay.d.ts.map +1 -1
- package/dist/elements/ChatInterface/ChatTypingIndicator.d.ts +2 -2
- package/dist/elements/ChatInterface/ChatTypingIndicator.d.ts.map +1 -1
- package/dist/elements/ChatInterface/index.js +1 -1
- package/dist/elements/ChatInterface/index.js.map +1 -1
- package/dist/elements/ChatInterface/index.mjs +1 -1
- package/dist/elements/ChatInterface/index.mjs.map +1 -1
- package/dist/elements/FeatureIcon/FeatureIcon.d.ts +3 -0
- package/dist/elements/FeatureIcon/FeatureIcon.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/FeatureIcon.styles.d.ts +17 -0
- package/dist/elements/FeatureIcon/FeatureIcon.styles.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/FeatureIcon.types.d.ts +137 -0
- package/dist/elements/FeatureIcon/FeatureIcon.types.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/index.d.ts +25 -0
- package/dist/elements/FeatureIcon/index.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/index.js +3 -0
- package/dist/elements/FeatureIcon/index.js.map +1 -0
- package/dist/elements/FeatureIcon/index.mjs +3 -0
- package/dist/elements/FeatureIcon/index.mjs.map +1 -0
- package/dist/elements/FileField/index.js +1 -1
- package/dist/elements/FileField/index.js.map +1 -1
- package/dist/elements/FileField/index.mjs +1 -1
- package/dist/elements/FileField/index.mjs.map +1 -1
- package/dist/elements/Filters/index.js +1 -1
- package/dist/elements/Filters/index.js.map +1 -1
- package/dist/elements/Filters/index.mjs +1 -1
- package/dist/elements/Filters/index.mjs.map +1 -1
- package/dist/elements/Modal/Modal.styles.d.ts +2 -2
- package/dist/elements/Modal/Modal.types.d.ts +2 -2
- package/dist/elements/NumberField/index.js +1 -1
- package/dist/elements/NumberField/index.js.map +1 -1
- package/dist/elements/NumberField/index.mjs +1 -1
- package/dist/elements/NumberField/index.mjs.map +1 -1
- package/dist/elements/PageTitle/index.js +1 -1
- package/dist/elements/PageTitle/index.js.map +1 -1
- package/dist/elements/PageTitle/index.mjs +1 -1
- package/dist/elements/PageTitle/index.mjs.map +1 -1
- package/dist/elements/Pagination/index.js +1 -1
- package/dist/elements/Pagination/index.js.map +1 -1
- package/dist/elements/Pagination/index.mjs +1 -1
- package/dist/elements/Pagination/index.mjs.map +1 -1
- package/dist/elements/Panel/Panel.d.ts +1 -1
- package/dist/elements/Panel/Panel.types.d.ts +2 -2
- package/dist/elements/PasswordField/index.js +1 -1
- package/dist/elements/PasswordField/index.js.map +1 -1
- package/dist/elements/PasswordField/index.mjs +1 -1
- package/dist/elements/PasswordField/index.mjs.map +1 -1
- package/dist/elements/RatingScale/RatingScale.d.ts.map +1 -1
- package/dist/elements/RatingScale/index.js +1 -1
- package/dist/elements/RatingScale/index.js.map +1 -1
- package/dist/elements/RatingScale/index.mjs +1 -1
- package/dist/elements/RatingScale/index.mjs.map +1 -1
- package/dist/elements/Resizable/index.js +1 -1
- package/dist/elements/Resizable/index.js.map +1 -1
- package/dist/elements/Resizable/index.mjs +1 -1
- package/dist/elements/Resizable/index.mjs.map +1 -1
- package/dist/elements/SearchField/index.js +1 -1
- package/dist/elements/SearchField/index.js.map +1 -1
- package/dist/elements/SearchField/index.mjs +1 -1
- package/dist/elements/SearchField/index.mjs.map +1 -1
- package/dist/elements/Select/Select.d.ts +3 -3
- package/dist/elements/Select/Select.d.ts.map +1 -1
- package/dist/elements/Sidebar/Sidebar.styles.d.ts +1 -1
- package/dist/elements/Sidebar/Sidebar.styles.d.ts.map +1 -1
- package/dist/elements/Sidebar/Sidebar.types.d.ts +2 -2
- package/dist/elements/Sidebar/SidebarRail.d.ts.map +1 -1
- package/dist/elements/Sidebar/index.js +1 -1
- package/dist/elements/Sidebar/index.js.map +1 -1
- package/dist/elements/Sidebar/index.mjs +1 -1
- package/dist/elements/Sidebar/index.mjs.map +1 -1
- package/dist/elements/Table/index.js +1 -1
- package/dist/elements/Table/index.js.map +1 -1
- package/dist/elements/Table/index.mjs +1 -1
- package/dist/elements/Table/index.mjs.map +1 -1
- package/dist/elements/TextField/index.js +1 -1
- package/dist/elements/TextField/index.js.map +1 -1
- package/dist/elements/TextField/index.mjs +1 -1
- package/dist/elements/TextField/index.mjs.map +1 -1
- package/dist/elements/Timeline/index.js +1 -1
- package/dist/elements/Timeline/index.js.map +1 -1
- package/dist/elements/Timeline/index.mjs +1 -1
- package/dist/elements/Timeline/index.mjs.map +1 -1
- package/dist/elements/Toast/index.js +1 -1
- package/dist/elements/Toast/index.js.map +1 -1
- package/dist/elements/Toast/index.mjs +1 -1
- package/dist/elements/Toast/index.mjs.map +1 -1
- package/dist/elements/Wizard/index.js +1 -1
- package/dist/elements/Wizard/index.js.map +1 -1
- package/dist/elements/Wizard/index.mjs +1 -1
- package/dist/elements/Wizard/index.mjs.map +1 -1
- package/dist/elements/index.d.ts +2 -0
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements/index.js +1 -1
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/index.mjs +1 -1
- package/dist/elements/index.mjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/styles/animations.css +15 -0
- package/package.json +16 -14
- package/src/elements/FeatureIcon/FeatureIcon.stories.tsx +164 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureIcon.d.ts","sourceRoot":"","sources":["../../../src/elements/FeatureIcon/FeatureIcon.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAiBhF,eAAO,MAAM,WAAW,8GA0DvB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeatureIcon container variants.
|
|
3
|
+
*
|
|
4
|
+
* Sizing also scales the inner SVG via `[&_svg]:size-*`, so any lucide / svg
|
|
5
|
+
* icon passed in is sized consistently without per-icon props.
|
|
6
|
+
*
|
|
7
|
+
* Colour values come from the Themis primary scale + semantic tokens:
|
|
8
|
+
* pale -> --primary-100, dark -> --primary-800, status -> --info-*, and the
|
|
9
|
+
* sidekick gradient ramps across the primary scale.
|
|
10
|
+
*/
|
|
11
|
+
export declare const featureIconVariants: (props?: ({
|
|
12
|
+
size?: "default" | "sm" | "lg" | "xl" | null | undefined;
|
|
13
|
+
background?: "status" | "primary" | "transparent" | "dark" | "pale" | "sidekick" | null | undefined;
|
|
14
|
+
corners?: "rounded" | "square" | "full" | null | undefined;
|
|
15
|
+
animated?: boolean | null | undefined;
|
|
16
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
17
|
+
//# sourceMappingURL=FeatureIcon.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureIcon.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/FeatureIcon/FeatureIcon.styles.ts"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB;;;;;8EA0C/B,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* FeatureIcon — a display-only icon inside a styled rounded container.
|
|
5
|
+
*
|
|
6
|
+
* Non-interactive by design (no onPress / href). It communicates a feature,
|
|
7
|
+
* section, or status visually. When `tooltip` is provided it becomes a
|
|
8
|
+
* keyboard-focusable, AT-named element wrapped in the Themis Tooltip.
|
|
9
|
+
*
|
|
10
|
+
* @see constitution.md Principle IV (Accessibility First — WCAG 2.2 AAA target)
|
|
11
|
+
*/
|
|
12
|
+
/** Container / icon size scale. */
|
|
13
|
+
export declare const FeatureIconSizeSchema: z.ZodEnum<{
|
|
14
|
+
default: "default";
|
|
15
|
+
sm: "sm";
|
|
16
|
+
lg: "lg";
|
|
17
|
+
xl: "xl";
|
|
18
|
+
}>;
|
|
19
|
+
export type FeatureIconSize = z.infer<typeof FeatureIconSizeSchema>;
|
|
20
|
+
/**
|
|
21
|
+
* Background treatment of the container.
|
|
22
|
+
* - transparent: no fill, brand-coloured icon
|
|
23
|
+
* - primary: solid brand
|
|
24
|
+
* - pale: light brand tint
|
|
25
|
+
* - dark: deep brand (--primary-800)
|
|
26
|
+
* - status: informational status surface
|
|
27
|
+
* - sidekick: Sidekick AI gradient
|
|
28
|
+
*/
|
|
29
|
+
export declare const FeatureIconBackgroundSchema: z.ZodEnum<{
|
|
30
|
+
status: "status";
|
|
31
|
+
primary: "primary";
|
|
32
|
+
transparent: "transparent";
|
|
33
|
+
dark: "dark";
|
|
34
|
+
pale: "pale";
|
|
35
|
+
sidekick: "sidekick";
|
|
36
|
+
}>;
|
|
37
|
+
export type FeatureIconBackground = z.infer<typeof FeatureIconBackgroundSchema>;
|
|
38
|
+
/** Corner radius treatment. */
|
|
39
|
+
export declare const FeatureIconCornersSchema: z.ZodEnum<{
|
|
40
|
+
rounded: "rounded";
|
|
41
|
+
square: "square";
|
|
42
|
+
full: "full";
|
|
43
|
+
}>;
|
|
44
|
+
export type FeatureIconCorners = z.infer<typeof FeatureIconCornersSchema>;
|
|
45
|
+
/**
|
|
46
|
+
* Predefined section icons (set by design guidelines).
|
|
47
|
+
* Extend this list as new product sections are standardised.
|
|
48
|
+
*/
|
|
49
|
+
export declare const FeatureIconSectionSchema: z.ZodEnum<{
|
|
50
|
+
messages: "messages";
|
|
51
|
+
jobs: "jobs";
|
|
52
|
+
candidates: "candidates";
|
|
53
|
+
interviews: "interviews";
|
|
54
|
+
reports: "reports";
|
|
55
|
+
tasks: "tasks";
|
|
56
|
+
settings: "settings";
|
|
57
|
+
notifications: "notifications";
|
|
58
|
+
}>;
|
|
59
|
+
export type FeatureIconSection = z.infer<typeof FeatureIconSectionSchema>;
|
|
60
|
+
export declare const FeatureIconPropsSchema: z.ZodObject<{
|
|
61
|
+
className: z.ZodOptional<z.ZodString>;
|
|
62
|
+
children: z.ZodOptional<z.ZodAny>;
|
|
63
|
+
id: z.ZodOptional<z.ZodString>;
|
|
64
|
+
'aria-label': z.ZodOptional<z.ZodString>;
|
|
65
|
+
'aria-labelledby': z.ZodOptional<z.ZodString>;
|
|
66
|
+
'aria-describedby': z.ZodOptional<z.ZodString>;
|
|
67
|
+
'aria-live': z.ZodOptional<z.ZodEnum<{
|
|
68
|
+
off: "off";
|
|
69
|
+
polite: "polite";
|
|
70
|
+
assertive: "assertive";
|
|
71
|
+
}>>;
|
|
72
|
+
'aria-hidden': z.ZodOptional<z.ZodBoolean>;
|
|
73
|
+
'data-testid': z.ZodOptional<z.ZodString>;
|
|
74
|
+
size: z.ZodOptional<z.ZodEnum<{
|
|
75
|
+
default: "default";
|
|
76
|
+
sm: "sm";
|
|
77
|
+
lg: "lg";
|
|
78
|
+
xl: "xl";
|
|
79
|
+
}>>;
|
|
80
|
+
background: z.ZodOptional<z.ZodEnum<{
|
|
81
|
+
status: "status";
|
|
82
|
+
primary: "primary";
|
|
83
|
+
transparent: "transparent";
|
|
84
|
+
dark: "dark";
|
|
85
|
+
pale: "pale";
|
|
86
|
+
sidekick: "sidekick";
|
|
87
|
+
}>>;
|
|
88
|
+
corners: z.ZodOptional<z.ZodEnum<{
|
|
89
|
+
rounded: "rounded";
|
|
90
|
+
square: "square";
|
|
91
|
+
full: "full";
|
|
92
|
+
}>>;
|
|
93
|
+
section: z.ZodOptional<z.ZodEnum<{
|
|
94
|
+
messages: "messages";
|
|
95
|
+
jobs: "jobs";
|
|
96
|
+
candidates: "candidates";
|
|
97
|
+
interviews: "interviews";
|
|
98
|
+
reports: "reports";
|
|
99
|
+
tasks: "tasks";
|
|
100
|
+
settings: "settings";
|
|
101
|
+
notifications: "notifications";
|
|
102
|
+
}>>;
|
|
103
|
+
icon: z.ZodOptional<z.ZodCustom<ReactNode, ReactNode>>;
|
|
104
|
+
animated: z.ZodOptional<z.ZodBoolean>;
|
|
105
|
+
tooltip: z.ZodOptional<z.ZodString>;
|
|
106
|
+
tooltipSide: z.ZodOptional<z.ZodEnum<{
|
|
107
|
+
top: "top";
|
|
108
|
+
bottom: "bottom";
|
|
109
|
+
left: "left";
|
|
110
|
+
right: "right";
|
|
111
|
+
}>>;
|
|
112
|
+
}, z.core.$strip>;
|
|
113
|
+
/**
|
|
114
|
+
* Explicit interface — avoids Zod 4 d.ts inference issues where optional
|
|
115
|
+
* fields can resolve as required through complex generics.
|
|
116
|
+
*/
|
|
117
|
+
export interface FeatureIconProps {
|
|
118
|
+
className?: string;
|
|
119
|
+
id?: string;
|
|
120
|
+
'data-testid'?: string;
|
|
121
|
+
'aria-label'?: string;
|
|
122
|
+
'aria-hidden'?: boolean;
|
|
123
|
+
size?: FeatureIconSize;
|
|
124
|
+
background?: FeatureIconBackground;
|
|
125
|
+
corners?: FeatureIconCorners;
|
|
126
|
+
/** Predefined section icon (per guidelines). Overridden by `icon`. */
|
|
127
|
+
section?: FeatureIconSection;
|
|
128
|
+
/** Custom icon node. Takes precedence over `section`. */
|
|
129
|
+
icon?: ReactNode;
|
|
130
|
+
/** Subtle idle animation (honours prefers-reduced-motion). */
|
|
131
|
+
animated?: boolean;
|
|
132
|
+
/** When set, wraps the icon in a tooltip with this text and names it for AT. */
|
|
133
|
+
tooltip?: string;
|
|
134
|
+
/** Tooltip placement (default 'top'). */
|
|
135
|
+
tooltipSide?: 'top' | 'bottom' | 'left' | 'right';
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=FeatureIcon.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureIcon.types.d.ts","sourceRoot":"","sources":["../../../src/elements/FeatureIcon/FeatureIcon.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;;;GAQG;AAEH,mCAAmC;AACnC,eAAO,MAAM,qBAAqB;;;;;EAAwC,CAAC;AAC3E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B;;;;;;;EAOtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,+BAA+B;AAC/B,eAAO,MAAM,wBAAwB;;;;EAAwC,CAAC;AAC9E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;EASnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBjC,CAAC;AAEH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,sEAAsE;IACtE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,yDAAyD;IACzD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,WAAW,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;CACnD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeatureIcon Component — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* A display-only icon inside a styled, rounded container. Non-interactive;
|
|
5
|
+
* communicates a feature, section, or status visually.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { FeatureIcon } from '@tribepad/themis/elements/FeatureIcon';
|
|
10
|
+
*
|
|
11
|
+
* // Section icon (from guidelines), pale background, full corners
|
|
12
|
+
* <FeatureIcon section="jobs" background="pale" corners="full" />
|
|
13
|
+
*
|
|
14
|
+
* // Custom icon with a tooltip (becomes keyboard-focusable + named)
|
|
15
|
+
* <FeatureIcon icon={<Sparkles />} background="sidekick" tooltip="Ask Sidekick AI" />
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @see FeatureIcon.tsx (Implementation)
|
|
19
|
+
* @see FeatureIcon.types.ts (Type definitions)
|
|
20
|
+
*/
|
|
21
|
+
export { FeatureIcon } from './FeatureIcon';
|
|
22
|
+
export { featureIconVariants } from './FeatureIcon.styles';
|
|
23
|
+
export type { FeatureIconProps, FeatureIconSize, FeatureIconBackground, FeatureIconCorners, FeatureIconSection, } from './FeatureIcon.types';
|
|
24
|
+
export { FeatureIconPropsSchema, FeatureIconSizeSchema, FeatureIconBackgroundSchema, FeatureIconCornersSchema, FeatureIconSectionSchema, } from './FeatureIcon.types';
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/FeatureIcon/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG3D,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function g(...e){return tailwindMerge.twMerge(clsx.clsx(e))}var F=classVarianceAuthority.cva(["z-50 overflow-hidden rounded-md px-3 py-1.5 text-sm","bg-[var(--content-foreground)] text-[var(--content-background)]","motion-safe:animate-in motion-safe:fade-in-0","data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0"],{variants:{side:{top:["motion-safe:slide-in-from-bottom-2","data-[exiting]:motion-safe:slide-out-to-bottom-2"],bottom:["motion-safe:slide-in-from-top-2","data-[exiting]:motion-safe:slide-out-to-top-2"],left:["motion-safe:slide-in-from-right-2","data-[exiting]:motion-safe:slide-out-to-right-2"],right:["motion-safe:slide-in-from-left-2","data-[exiting]:motion-safe:slide-out-to-left-2"]}},defaultVariants:{side:"top"}}),S=classVarianceAuthority.cva("fill-[var(--content-foreground)]",{variants:{side:{top:"rotate-180",bottom:"rotate-0",left:"rotate-90",right:"-rotate-90"}},defaultVariants:{side:"top"}});function I(e){if(!e)return "top";let t=e.split(" ")[0];return t==="top"||t==="bottom"||t==="left"||t==="right"?t:"top"}function L({children:e,delay:t=700,closeDelay:i=300,trigger:s="hover",isOpen:c,defaultOpen:d=false,onOpenChange:p,isDisabled:u=false}){return jsxRuntime.jsx(reactAriaComponents.TooltipTrigger,{delay:s==="focus"?99999999:t,closeDelay:i,isOpen:c,defaultOpen:d,onOpenChange:p,isDisabled:u,children:e})}L.displayName="Tooltip";function D({children:e}){return e}D.displayName="TooltipTrigger";function R({children:e,side:t="top",sideOffset:i=4,alignOffset:s=0,shouldFlip:c=true,showArrow:d=false,arrowSize:p=8,className:u,...f}){return jsxRuntime.jsx(reactAriaComponents.Tooltip,{placement:t,offset:i,crossOffset:s,shouldFlip:c,...f,className:reactAriaComponents.composeRenderProps(u,(l,m)=>{let x=I(m.placement);return g(F({side:x}),l)}),children:l=>{let m=I(l.placement);return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[d&&jsxRuntime.jsx(reactAriaComponents.OverlayArrow,{children:jsxRuntime.jsx("svg",{width:p,height:p,viewBox:"0 0 8 8",className:S({side:m}),"data-testid":"tooltip-arrow",children:jsxRuntime.jsx("path",{d:"M0 0 L4 4 L8 0"})})}),e]})}})}R.displayName="TooltipContent";var _=L,h=D,v=R;var w=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var M=["focus-visible:outline-none","focus-visible:ring-2","focus-visible:ring-[var(--ring)]","focus-visible:ring-offset-2"];var P=["motion-reduce:transition-none","motion-reduce:animate-none"],k=["transition-colors","duration-200"];function B(...e){return e.flatMap(t=>Array.isArray(t)?[...t]:[t])}var O=classVarianceAuthority.cva(B("inline-flex shrink-0 items-center justify-center overflow-hidden",M,k,P),{variants:{size:{sm:"h-8 w-8 [&_svg]:size-4",default:"h-10 w-10 [&_svg]:size-5",lg:"h-12 w-12 [&_svg]:size-6",xl:"h-16 w-16 [&_svg]:size-8"},background:{transparent:"bg-transparent text-[var(--primary)]",primary:"bg-[var(--primary)] text-[var(--primary-foreground)]",pale:"bg-[var(--primary-100)] text-[var(--primary-700)]",dark:"bg-[var(--primary-800)] text-[var(--primary-foreground)]",status:"bg-[var(--info-background)] text-[var(--info-foreground)]",sidekick:"bg-gradient-to-br from-[var(--primary-400)] via-[var(--primary)] to-[var(--primary-700)] text-[var(--primary-foreground)]"},corners:{square:"rounded-none",rounded:"rounded-lg",full:"rounded-full"},animated:{true:"[&_svg]:feature-icon-animated [&_svg]:motion-reduce:animate-none",false:""}},defaultVariants:{size:"default",background:"pale",corners:"rounded",animated:false}});var ut={jobs:jsxRuntime.jsx(lucideReact.Briefcase,{"aria-hidden":"true"}),candidates:jsxRuntime.jsx(lucideReact.Users,{"aria-hidden":"true"}),interviews:jsxRuntime.jsx(lucideReact.CalendarDays,{"aria-hidden":"true"}),messages:jsxRuntime.jsx(lucideReact.MessageSquare,{"aria-hidden":"true"}),reports:jsxRuntime.jsx(lucideReact.ChartColumn,{"aria-hidden":"true"}),tasks:jsxRuntime.jsx(lucideReact.ListChecks,{"aria-hidden":"true"}),settings:jsxRuntime.jsx(lucideReact.Settings,{"aria-hidden":"true"}),notifications:jsxRuntime.jsx(lucideReact.Bell,{"aria-hidden":"true"})},z=react.forwardRef(function({className:t,id:i,size:s,background:c,corners:d,section:p,icon:u,animated:f,tooltip:l,tooltipSide:m="top","aria-label":x,"aria-hidden":E,"data-testid":Z="feature-icon"},q){let $=u??(p?ut[p]:null),b=x??l,T=b==null,y=jsxRuntime.jsx("span",{ref:q,id:i,"data-testid":Z,className:g(O({size:s,background:c,corners:d,animated:f}),t),role:T?void 0:"img","aria-label":T?void 0:b,"aria-hidden":T?E??true:E,children:$});return l==null?y:jsxRuntime.jsxs(_,{children:[jsxRuntime.jsx(h,{children:jsxRuntime.jsx(reactAriaComponents.Focusable,{children:y})}),jsxRuntime.jsx(v,{side:m,children:l})]})});z.displayName="FeatureIcon";var U=zod.z.enum(["sm","default","lg","xl"]),V=zod.z.enum(["transparent","primary","pale","dark","status","sidekick"]),G=zod.z.enum(["square","rounded","full"]),H=zod.z.enum(["jobs","candidates","interviews","messages","reports","tasks","settings","notifications"]),gt=w.extend({size:U.optional(),background:V.optional(),corners:G.optional(),section:H.optional(),icon:zod.z.custom().optional(),animated:zod.z.boolean().optional(),tooltip:zod.z.string().optional(),tooltipSide:zod.z.enum(["top","bottom","left","right"]).optional()});exports.FeatureIcon=z;exports.FeatureIconBackgroundSchema=V;exports.FeatureIconCornersSchema=G;exports.FeatureIconPropsSchema=gt;exports.FeatureIconSectionSchema=H;exports.FeatureIconSizeSchema=U;exports.featureIconVariants=O;//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Tooltip/Tooltip.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/styles/shared-variants.ts","../../../src/elements/FeatureIcon/FeatureIcon.styles.ts","../../../src/elements/FeatureIcon/FeatureIcon.tsx","../../../src/elements/FeatureIcon/FeatureIcon.types.ts"],"names":["cn","inputs","twMerge","clsx","tooltipContentVariants","cva","tooltipArrowVariants","placementToSide","placement","basePlacement","TooltipRoot","children","delay","closeDelay","trigger","isOpen","defaultOpen","onOpenChange","isDisabled","jsx","AriaTooltipTrigger","TooltipTriggerComponent","TooltipContentComponent","side","sideOffset","alignOffset","shouldFlip","showArrow","arrowSize","className","restProps","AriaTooltip","composeRenderProps","renderProps","actualSide","jsxs","Fragment","OverlayArrow","Tooltip","TooltipTrigger","TooltipContent","BaseComponentPropsSchema","z","FOCUS_VISIBLE_RING","REDUCED_MOTION","TRANSITION_COLORS","combineStyles","styles","s","featureIconVariants","SECTION_ICONS","Briefcase","Users","CalendarDays","MessageSquare","ChartColumn","ListChecks","Settings","Bell","FeatureIcon","forwardRef","id","size","background","corners","section","icon","animated","tooltip","tooltipSide","ariaLabel","ariaHidden","testId","ref","resolvedIcon","accessibleName","decorative","visual","Focusable","FeatureIconSizeSchema","FeatureIconBackgroundSchema","FeatureIconCornersSchema","FeatureIconSectionSchema","FeatureIconPropsSchema"],"mappings":"oTAcO,SAASA,CAAAA,CAAAA,GAAMC,CAAAA,CAA8B,CAClD,OAAOC,qBAAAA,CAAQC,SAAAA,CAAKF,CAAM,CAAC,CAC7B,CCsBO,IAAMG,CAAAA,CAAyBC,0BAAAA,CAEpC,CACE,qDAAA,CAEA,iEAAA,CAEA,8CAAA,CAEA,8EACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,GAAA,CAAK,CACH,oCAAA,CACA,kDACF,EACA,MAAA,CAAQ,CACN,iCAAA,CACA,+CACF,CAAA,CACA,IAAA,CAAM,CACJ,mCAAA,CACA,iDACF,CAAA,CACA,KAAA,CAAO,CACL,kCAAA,CACA,gDACF,CACF,CACF,CAAA,CACA,eAAA,CAAiB,CACf,IAAA,CAAM,KACR,CACF,CACF,CAAA,CASaC,CAAAA,CAAuBD,0BAAAA,CAElC,kCAAA,CACA,CACE,SAAU,CACR,IAAA,CAAM,CACJ,GAAA,CAAK,YAAA,CACL,MAAA,CAAQ,WACR,IAAA,CAAM,WAAA,CACN,KAAA,CAAO,YACT,CACF,CAAA,CACA,gBAAiB,CACf,IAAA,CAAM,KACR,CACF,CACF,CAAA,CAOA,SAASE,CAAAA,CAAgBC,CAAAA,CAAmD,CAC1E,GAAI,CAACA,CAAAA,CAAW,OAAO,KAAA,CAEvB,IAAMC,CAAAA,CAAgBD,CAAAA,CAAU,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,CAC5C,OAAIC,CAAAA,GAAkB,KAAA,EAASA,CAAAA,GAAkB,UAC7CA,CAAAA,GAAkB,MAAA,EAAUA,CAAAA,GAAkB,OAAA,CACzCA,CAAAA,CAEF,KACT,CAYA,SAASC,CAAAA,CAAY,CACnB,QAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CAAQ,IACR,UAAA,CAAAC,CAAAA,CAAa,GAAA,CACb,OAAA,CAAAC,CAAAA,CAAU,OAAA,CACV,OAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CAAc,KAAA,CACd,YAAA,CAAAC,CAAAA,CACA,WAAAC,CAAAA,CAAa,KACf,CAAA,CAA+B,CAM7B,OACEC,cAAAA,CAACC,kCAAAA,CAAA,CACC,KAAA,CAJmBN,CAAAA,GAAY,OAAA,CAAU,QAAA,CAAWF,CAAAA,CAKpD,UAAA,CAAYC,EACZ,MAAA,CAAQE,CAAAA,CACR,WAAA,CAAaC,CAAAA,CACb,YAAA,CAAcC,CAAAA,CACd,WAAYC,CAAAA,CAEX,QAAA,CAAAP,CAAAA,CACH,CAEJ,CAEAD,CAAAA,CAAY,YAAc,SAAA,CAc1B,SAASW,CAAAA,CAAwB,CAC/B,QAAA,CAAAV,CACF,CAAA,CAAsC,CAGpC,OAAOA,CACT,CAEAU,CAAAA,CAAwB,WAAA,CAAc,gBAAA,CAWtC,SAASC,CAAAA,CAAwB,CAC/B,QAAA,CAAAX,CAAAA,CACA,IAAA,CAAAY,CAAAA,CAAO,MACP,UAAA,CAAAC,CAAAA,CAAa,CAAA,CACb,WAAA,CAAAC,CAAAA,CAAc,CAAA,CACd,WAAAC,CAAAA,CAAa,IAAA,CACb,SAAA,CAAAC,CAAAA,CAAY,KAAA,CACZ,SAAA,CAAAC,EAAY,CAAA,CACZ,SAAA,CAAAC,CAAAA,CACA,GAAGC,CACL,CAAA,CAAmE,CACjE,OACEX,cAAAA,CAACY,2BAAAA,CAAA,CACC,SAAA,CAAWR,CAAAA,CACX,OAAQC,CAAAA,CACR,WAAA,CAAaC,CAAAA,CACb,UAAA,CAAYC,CAAAA,CACX,GAAGI,EACJ,SAAA,CAAWE,sCAAAA,CAAmBH,CAAAA,CAAW,CAACA,CAAAA,CAAWI,CAAAA,GAAgB,CAEnE,IAAMC,CAAAA,CAAa3B,CAAAA,CAAgB0B,CAAAA,CAAY,SAAS,CAAA,CACxD,OAAOjC,EACLI,CAAAA,CAAuB,CAAE,IAAA,CAAM8B,CAAW,CAAC,CAAA,CAC3CL,CACF,CACF,CAAC,CAAA,CAEA,QAAA,CAACI,CAAAA,EAAgB,CAChB,IAAMC,CAAAA,CAAa3B,CAAAA,CAAgB0B,CAAAA,CAAY,SAAS,CAAA,CACxD,OACEE,eAAAA,CAAAC,mBAAAA,CAAA,CACG,QAAA,CAAA,CAAAT,CAAAA,EACCR,cAAAA,CAACkB,gCAAAA,CAAA,CACC,SAAAlB,cAAAA,CAAC,KAAA,CAAA,CACC,KAAA,CAAOS,CAAAA,CACP,MAAA,CAAQA,CAAAA,CACR,QAAQ,SAAA,CACR,SAAA,CAAWtB,CAAAA,CAAqB,CAAE,IAAA,CAAM4B,CAAW,CAAC,CAAA,CACpD,aAAA,CAAY,eAAA,CAEZ,QAAA,CAAAf,cAAAA,CAAC,MAAA,CAAA,CAAK,CAAA,CAAE,gBAAA,CAAiB,CAAA,CAC3B,CAAA,CACF,CAAA,CAEDR,CAAAA,CAAAA,CACH,CAEJ,CAAA,CACF,CAEJ,CAEAW,CAAAA,CAAwB,WAAA,CAAc,gBAAA,CAmD/B,IAAMgB,EAAU5B,CAAAA,CACV6B,CAAAA,CAAiBlB,CAAAA,CACjBmB,CAAAA,CAAiBlB,CAAAA,CC7RvB,IAAMmB,CAAAA,CAA2BC,KAAAA,CAAE,MAAA,CAAO,CAE/C,UAAWA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG/B,QAAA,CAAUA,MAAE,GAAA,EAAI,CAAE,QAAA,EAAS,CAC3B,EAAA,CAAIA,KAAAA,CAAE,QAAO,CAAE,QAAA,EAAS,CAGxB,YAAA,CAAcA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAClC,iBAAA,CAAmBA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAC9B,kBAAA,CAAoBA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CACxC,YAAaA,KAAAA,CAAE,IAAA,CAAK,CAAC,KAAA,CAAO,QAAA,CAAU,WAAW,CAAC,CAAA,CAAE,QAAA,EAAS,CAC7D,aAAA,CAAeA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAGpC,aAAA,CAAeA,KAAAA,CAAE,MAAA,EAAO,CAAE,UAC5B,CAAC,CAAA,CCEM,IAAMC,CAAAA,CAAqB,CAChC,4BAAA,CACA,sBAAA,CACA,kCAAA,CACA,6BACF,CAAA,CAsTO,IAAMC,CAAAA,CAAiB,CAC5B,+BAAA,CACA,4BACF,CAAA,CAKaC,CAAAA,CAAoB,CAC/B,mBAAA,CACA,cACF,CAAA,CA6BO,SAASC,CAAAA,CAAAA,GAAiBC,CAAAA,CAAkD,CACjF,OAAOA,CAAAA,CAAO,OAAA,CAAQC,CAAAA,EAAK,KAAA,CAAM,OAAA,CAAQA,CAAC,CAAA,CAAI,CAAC,GAAGA,CAAC,CAAA,CAAI,CAACA,CAAC,CAAC,CAC5D,CC/WO,IAAMC,CAAAA,CAAsB5C,0BAAAA,CACjCyC,CAAAA,CACE,kEAAA,CACAH,CAAAA,CACAE,CAAAA,CACAD,CACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,wBAAA,CACJ,OAAA,CAAS,0BAAA,CACT,GAAI,0BAAA,CACJ,EAAA,CAAI,0BACN,CAAA,CACA,UAAA,CAAY,CACV,YAAa,sCAAA,CACb,OAAA,CAAS,sDAAA,CACT,IAAA,CAAM,mDAAA,CACN,IAAA,CAAM,0DAAA,CACN,MAAA,CAAQ,2DAAA,CACR,QAAA,CACE,2HACJ,CAAA,CACA,OAAA,CAAS,CACP,OAAQ,cAAA,CACR,OAAA,CAAS,YAAA,CACT,IAAA,CAAM,cACR,CAAA,CACA,SAAU,CAER,IAAA,CAAM,kEAAA,CACN,KAAA,CAAO,EACT,CACF,EACA,eAAA,CAAiB,CACf,IAAA,CAAM,SAAA,CACN,UAAA,CAAY,MAAA,CACZ,OAAA,CAAS,SAAA,CACT,QAAA,CAAU,KACZ,CACF,CACF,ECnBA,IAAMM,EAAAA,CAAuD,CAC3D,KAAM/B,cAAAA,CAACgC,qBAAAA,CAAA,CAAU,aAAA,CAAY,MAAA,CAAO,CAAA,CACpC,WAAYhC,cAAAA,CAACiC,iBAAAA,CAAA,CAAM,aAAA,CAAY,MAAA,CAAO,CAAA,CACtC,UAAA,CAAYjC,cAAAA,CAACkC,wBAAAA,CAAA,CAAa,aAAA,CAAY,MAAA,CAAO,CAAA,CAC7C,QAAA,CAAUlC,eAACmC,yBAAAA,CAAA,CAAc,aAAA,CAAY,MAAA,CAAO,CAAA,CAC5C,OAAA,CAASnC,eAACoC,uBAAAA,CAAA,CAAY,aAAA,CAAY,MAAA,CAAO,CAAA,CACzC,KAAA,CAAOpC,eAACqC,sBAAAA,CAAA,CAAW,aAAA,CAAY,MAAA,CAAO,CAAA,CACtC,QAAA,CAAUrC,cAAAA,CAACsC,oBAAAA,CAAA,CAAS,aAAA,CAAY,MAAA,CAAO,CAAA,CACvC,aAAA,CAAetC,cAAAA,CAACuC,iBAAA,CAAK,aAAA,CAAY,MAAA,CAAO,CAC1C,CAAA,CAEaC,CAAAA,CAAcC,iBACzB,SACE,CACE,SAAA,CAAA/B,CAAAA,CACA,EAAA,CAAAgC,CAAAA,CACA,KAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,EACA,IAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CACA,YAAAC,CAAAA,CAAc,KAAA,CACd,YAAA,CAAcC,CAAAA,CACd,aAAA,CAAeC,CAAAA,CACf,cAAeC,CAAAA,CAAS,cAC1B,CAAA,CACAC,CAAAA,CACA,CAEA,IAAMC,EAA0BR,CAAAA,GAASD,CAAAA,CAAUf,EAAAA,CAAce,CAAO,CAAA,CAAI,IAAA,CAAA,CAGtEU,CAAAA,CAAiBL,CAAAA,EAAaF,CAAAA,CAC9BQ,CAAAA,CAAaD,CAAAA,EAAkB,IAAA,CAE/BE,CAAAA,CACJ1D,cAAAA,CAAC,QACC,GAAA,CAAKsD,CAAAA,CACL,EAAA,CAAIZ,CAAAA,CACJ,aAAA,CAAaW,CAAAA,CACb,UAAWxE,CAAAA,CACTiD,CAAAA,CAAoB,CAAE,IAAA,CAAAa,CAAAA,CAAM,UAAA,CAAAC,EAAY,OAAA,CAAAC,CAAAA,CAAS,QAAA,CAAAG,CAAS,CAAC,CAAA,CAC3DtC,CACF,CAAA,CACA,IAAA,CAAM+C,CAAAA,CAAa,MAAA,CAAY,KAAA,CAC/B,YAAA,CAAYA,CAAAA,CAAa,OAAYD,CAAAA,CACrC,aAAA,CAAaC,CAAAA,CAAaL,CAAAA,EAAc,IAAA,CAAOA,CAAAA,CAE9C,SAAAG,CAAAA,CACH,CAAA,CAGF,OAAIN,CAAAA,EAAW,IAAA,CACNS,CAAAA,CAMP1C,gBAACG,CAAAA,CAAA,CACC,QAAA,CAAA,CAAAnB,cAAAA,CAACoB,CAAAA,CAAA,CACC,QAAA,CAAApB,cAAAA,CAAC2D,6BAAAA,CAAA,CAAW,QAAA,CAAAD,CAAAA,CAAO,CAAA,CACrB,CAAA,CACA1D,eAACqB,CAAAA,CAAA,CAAe,IAAA,CAAM6B,CAAAA,CAAc,QAAA,CAAAD,CAAAA,CAAQ,GAC9C,CAEJ,CACF,EAEAT,CAAAA,CAAY,WAAA,CAAc,aAAA,CCjGnB,IAAMoB,CAAAA,CAAwBrC,KAAAA,CAAE,IAAA,CAAK,CAAC,IAAA,CAAM,SAAA,CAAW,IAAA,CAAM,IAAI,CAAC,CAAA,CAY5DsC,EAA8BtC,KAAAA,CAAE,IAAA,CAAK,CAChD,aAAA,CACA,SAAA,CACA,MAAA,CACA,OACA,QAAA,CACA,UACF,CAAC,CAAA,CAIYuC,CAAAA,CAA2BvC,KAAAA,CAAE,KAAK,CAAC,QAAA,CAAU,SAAA,CAAW,MAAM,CAAC,CAAA,CAO/DwC,CAAAA,CAA2BxC,KAAAA,CAAE,IAAA,CAAK,CAC7C,MAAA,CACA,YAAA,CACA,YAAA,CACA,UAAA,CACA,UACA,OAAA,CACA,UAAA,CACA,eACF,CAAC,CAAA,CAGYyC,EAAAA,CAAyB1C,EAAyB,MAAA,CAAO,CAEpE,IAAA,CAAMsC,CAAAA,CAAsB,QAAA,EAAS,CAErC,WAAYC,CAAAA,CAA4B,QAAA,EAAS,CAEjD,OAAA,CAASC,CAAAA,CAAyB,QAAA,EAAS,CAE3C,OAAA,CAASC,CAAAA,CAAyB,QAAA,EAAS,CAE3C,IAAA,CAAMxC,KAAAA,CAAE,MAAA,GAAoB,QAAA,EAAS,CAErC,QAAA,CAAUA,KAAAA,CAAE,OAAA,EAAQ,CAAE,UAAS,CAE/B,OAAA,CAASA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAEpB,WAAA,CAAaA,KAAAA,CAAE,IAAA,CAAK,CAAC,KAAA,CAAO,QAAA,CAAU,MAAA,CAAQ,OAAO,CAAC,CAAA,CAAE,QAAA,EAC1D,CAAC","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Tooltip Component - Implementation\n *\n * Accessible tooltip component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure.\n *\n * @see plan.md (Implementation plan)\n * @see Tooltip.types.ts (Zod schemas)\n * @see tooltip-prd.md (Full requirements)\n */\n\nimport { type ReactElement } from 'react';\nimport {\n TooltipTrigger as AriaTooltipTrigger,\n Tooltip as AriaTooltip,\n OverlayArrow,\n composeRenderProps,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport type {\n TooltipProps,\n TooltipTriggerProps,\n TooltipContentProps,\n TooltipArrowProps,\n TooltipSide,\n} from './Tooltip.types';\n\n/**\n * CVA Variants for TooltipContent\n *\n * Placement-based animations and high-contrast inverted colors.\n *\n * @see plan.md (CVA Variant Structure)\n * @see tooltip-prd.md US-2 (Configurable Placement)\n */\nexport const tooltipContentVariants = cva(\n // Base styles\n [\n \"z-50 overflow-hidden rounded-md px-3 py-1.5 text-sm\",\n // Inverted colors for high contrast (7:1 ratio)\n \"bg-[var(--content-foreground)] text-[var(--content-background)]\",\n // Entry animation base (motion-safe guarded)\n \"motion-safe:animate-in motion-safe:fade-in-0\",\n // Exit animation\n \"data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0\",\n ],\n {\n variants: {\n side: {\n top: [\n \"motion-safe:slide-in-from-bottom-2\",\n \"data-[exiting]:motion-safe:slide-out-to-bottom-2\",\n ],\n bottom: [\n \"motion-safe:slide-in-from-top-2\",\n \"data-[exiting]:motion-safe:slide-out-to-top-2\",\n ],\n left: [\n \"motion-safe:slide-in-from-right-2\",\n \"data-[exiting]:motion-safe:slide-out-to-right-2\",\n ],\n right: [\n \"motion-safe:slide-in-from-left-2\",\n \"data-[exiting]:motion-safe:slide-out-to-left-2\",\n ],\n },\n },\n defaultVariants: {\n side: \"top\",\n },\n }\n);\n\n/**\n * CVA Variants for TooltipArrow\n *\n * Rotation based on placement for correct arrow pointing direction.\n *\n * @see tooltip-prd.md US-2 (Arrow Indicator)\n */\nexport const tooltipArrowVariants = cva(\n // Base arrow styles\n \"fill-[var(--content-foreground)]\",\n {\n variants: {\n side: {\n top: \"rotate-180\",\n bottom: \"rotate-0\",\n left: \"rotate-90\",\n right: \"-rotate-90\",\n },\n },\n defaultVariants: {\n side: \"top\",\n },\n }\n);\n\n/**\n * Map React Aria placement to our side prop\n * React Aria uses placement prop with values like 'top', 'bottom', etc.\n * PlacementAxis can be 'top' | 'bottom' | 'left' | 'right' | null\n */\nfunction placementToSide(placement: string | null | undefined): TooltipSide {\n if (!placement) return 'top';\n // Extract the base placement (e.g., 'top start' -> 'top')\n const basePlacement = placement.split(' ')[0];\n if (basePlacement === 'top' || basePlacement === 'bottom' ||\n basePlacement === 'left' || basePlacement === 'right') {\n return basePlacement;\n }\n return 'top';\n}\n\n/**\n * Tooltip Root Component\n *\n * Manages tooltip open/close state, delays, and trigger behavior.\n * Wraps React Aria's TooltipTrigger with delay configuration.\n *\n * @see tooltip-prd.md US-1 (Basic Usage)\n * @see tooltip-prd.md US-3 (Delay Configuration)\n * @see tooltip-prd.md US-7 (Controlled State)\n */\nfunction TooltipRoot({\n children,\n delay = 700,\n closeDelay = 300,\n trigger = 'hover',\n isOpen,\n defaultOpen = false,\n onOpenChange,\n isDisabled = false,\n}: TooltipProps): ReactElement {\n // React Aria doesn't have a direct trigger mode prop\n // 'focus' mode is achieved by setting delay to a very high value\n // and relying on focus to trigger immediately\n const effectiveDelay = trigger === 'focus' ? 99999999 : delay;\n\n return (\n <AriaTooltipTrigger\n delay={effectiveDelay}\n closeDelay={closeDelay}\n isOpen={isOpen}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n isDisabled={isDisabled}\n >\n {children}\n </AriaTooltipTrigger>\n );\n}\n\nTooltipRoot.displayName = 'Tooltip';\n\n/**\n * TooltipTrigger Component\n *\n * Wrapper for the element that triggers the tooltip.\n * The child element must be focusable (or wrapped with Focusable).\n *\n * React Aria's TooltipTrigger automatically applies:\n * - aria-describedby linking to tooltip\n * - Hover and focus event handlers\n *\n * @see tooltip-prd.md US-5 (Non-Button Triggers)\n */\nfunction TooltipTriggerComponent({\n children,\n}: TooltipTriggerProps): ReactElement {\n // React Aria's TooltipTrigger expects the trigger element as a direct child\n // We pass through the child element directly\n return children as ReactElement;\n}\n\nTooltipTriggerComponent.displayName = 'TooltipTrigger';\n\n/**\n * TooltipContent Component\n *\n * The actual tooltip overlay that appears.\n * Supports placement, offset, and optional arrow.\n *\n * @see tooltip-prd.md US-2 (Placement and Arrow)\n * @see tooltip-prd.md Technical Implementation Details\n */\nfunction TooltipContentComponent({\n children,\n side = 'top',\n sideOffset = 4,\n alignOffset = 0,\n shouldFlip = true,\n showArrow = false,\n arrowSize = 8,\n className,\n ...restProps\n}: TooltipContentProps & { 'data-testid'?: string }): ReactElement {\n return (\n <AriaTooltip\n placement={side}\n offset={sideOffset}\n crossOffset={alignOffset}\n shouldFlip={shouldFlip}\n {...restProps}\n className={composeRenderProps(className, (className, renderProps) => {\n // Get actual placement from render props for animation direction\n const actualSide = placementToSide(renderProps.placement);\n return cn(\n tooltipContentVariants({ side: actualSide }),\n className\n );\n })}\n >\n {(renderProps) => {\n const actualSide = placementToSide(renderProps.placement);\n return (\n <>\n {showArrow && (\n <OverlayArrow>\n <svg\n width={arrowSize}\n height={arrowSize}\n viewBox=\"0 0 8 8\"\n className={tooltipArrowVariants({ side: actualSide })}\n data-testid=\"tooltip-arrow\"\n >\n <path d=\"M0 0 L4 4 L8 0\" />\n </svg>\n </OverlayArrow>\n )}\n {children}\n </>\n );\n }}\n </AriaTooltip>\n );\n}\n\nTooltipContentComponent.displayName = 'TooltipContent';\n\n/**\n * TooltipArrow Component\n *\n * Optional arrow component for custom arrow rendering.\n * Automatically positioned based on tooltip placement.\n *\n * Note: This is an alternative to using showArrow prop on TooltipContent.\n * Use this when you need custom arrow styling or rendering.\n *\n * @see tooltip-prd.md US-2 (Arrow Indicator)\n */\nfunction TooltipArrowComponent({\n size = 8,\n className,\n 'data-testid': dataTestId = 'tooltip-arrow',\n ...restProps\n}: TooltipArrowProps & { 'data-testid'?: string }): ReactElement {\n // This component is designed to be used inside TooltipContent\n // The actual positioning is handled by OverlayArrow from React Aria\n return (\n <OverlayArrow>\n {({ placement }) => {\n const side = placementToSide(placement);\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 8 8\"\n className={cn(tooltipArrowVariants({ side }), className)}\n data-testid={dataTestId}\n {...restProps}\n >\n <path d=\"M0 0 L4 4 L8 0\" />\n </svg>\n );\n }}\n </OverlayArrow>\n );\n}\n\nTooltipArrowComponent.displayName = 'TooltipArrow';\n\n/**\n * Export all components\n *\n * Following Themis pattern - export individual components\n * No Object.assign compound pattern for Tooltip since React Aria\n * expects specific component hierarchy.\n */\nexport const Tooltip = TooltipRoot;\nexport const TooltipTrigger = TooltipTriggerComponent;\nexport const TooltipContent = TooltipContentComponent;\nexport const TooltipArrow = TooltipArrowComponent;\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva } from 'class-variance-authority';\nimport {\n combineStyles,\n FOCUS_VISIBLE_RING,\n REDUCED_MOTION,\n TRANSITION_COLORS,\n} from '../../styles/shared-variants';\n\n/**\n * FeatureIcon container variants.\n *\n * Sizing also scales the inner SVG via `[&_svg]:size-*`, so any lucide / svg\n * icon passed in is sized consistently without per-icon props.\n *\n * Colour values come from the Themis primary scale + semantic tokens:\n * pale -> --primary-100, dark -> --primary-800, status -> --info-*, and the\n * sidekick gradient ramps across the primary scale.\n */\nexport const featureIconVariants = cva(\n combineStyles(\n 'inline-flex shrink-0 items-center justify-center overflow-hidden',\n FOCUS_VISIBLE_RING,\n TRANSITION_COLORS,\n REDUCED_MOTION,\n ),\n {\n variants: {\n size: {\n sm: 'h-8 w-8 [&_svg]:size-4',\n default: 'h-10 w-10 [&_svg]:size-5',\n lg: 'h-12 w-12 [&_svg]:size-6',\n xl: 'h-16 w-16 [&_svg]:size-8',\n },\n background: {\n transparent: 'bg-transparent text-[var(--primary)]',\n primary: 'bg-[var(--primary)] text-[var(--primary-foreground)]',\n pale: 'bg-[var(--primary-100)] text-[var(--primary-700)]',\n dark: 'bg-[var(--primary-800)] text-[var(--primary-foreground)]',\n status: 'bg-[var(--info-background)] text-[var(--info-foreground)]',\n sidekick:\n 'bg-gradient-to-br from-[var(--primary-400)] via-[var(--primary)] to-[var(--primary-700)] text-[var(--primary-foreground)]',\n },\n corners: {\n square: 'rounded-none',\n rounded: 'rounded-lg',\n full: 'rounded-full',\n },\n animated: {\n // Animates the inner icon (svg), not the container.\n true: '[&_svg]:feature-icon-animated [&_svg]:motion-reduce:animate-none',\n false: '',\n },\n },\n defaultVariants: {\n size: 'default',\n background: 'pale',\n corners: 'rounded',\n animated: false,\n },\n },\n);\n","'use client';\n\n/**\n * FeatureIcon Component\n *\n * A display-only icon inside a styled, rounded container. Non-interactive by\n * design — it does not handle clicks or navigation. Use it to represent a\n * feature, product section, or status.\n *\n * Accessibility:\n * - Purely decorative by default (aria-hidden) so it adds no screen-reader noise.\n * - Give it meaning with `aria-label` and/or `tooltip`; it then exposes\n * role=\"img\" with an accessible name.\n * - When `tooltip` is set the icon becomes keyboard-focusable (via React Aria\n * Focusable) and uses the Themis Tooltip, which is hoverable + dismissible\n * (WCAG 1.4.13).\n *\n * @see constitution.md Principle IV (Accessibility First)\n */\n\nimport { forwardRef, type ReactNode } from 'react';\nimport { Focusable } from 'react-aria-components';\nimport {\n Bell,\n Briefcase,\n CalendarDays,\n ChartColumn,\n ListChecks,\n MessageSquare,\n Settings,\n Users,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip';\nimport { featureIconVariants } from './FeatureIcon.styles';\nimport type { FeatureIconProps, FeatureIconSection } from './FeatureIcon.types';\n\n/**\n * Section → icon map (set by design guidelines).\n * Extend alongside FeatureIconSectionSchema as sections are standardised.\n */\nconst SECTION_ICONS: Record<FeatureIconSection, ReactNode> = {\n jobs: <Briefcase aria-hidden=\"true\" />,\n candidates: <Users aria-hidden=\"true\" />,\n interviews: <CalendarDays aria-hidden=\"true\" />,\n messages: <MessageSquare aria-hidden=\"true\" />,\n reports: <ChartColumn aria-hidden=\"true\" />,\n tasks: <ListChecks aria-hidden=\"true\" />,\n settings: <Settings aria-hidden=\"true\" />,\n notifications: <Bell aria-hidden=\"true\" />,\n};\n\nexport const FeatureIcon = forwardRef<HTMLSpanElement, FeatureIconProps>(\n function FeatureIcon(\n {\n className,\n id,\n size,\n background,\n corners,\n section,\n icon,\n animated,\n tooltip,\n tooltipSide = 'top',\n 'aria-label': ariaLabel,\n 'aria-hidden': ariaHidden,\n 'data-testid': testId = 'feature-icon',\n },\n ref,\n ) {\n // Icon precedence: custom `icon` > `section` > none.\n const resolvedIcon: ReactNode = icon ?? (section ? SECTION_ICONS[section] : null);\n\n // Accessible name: explicit aria-label wins, otherwise the tooltip text.\n const accessibleName = ariaLabel ?? tooltip;\n const decorative = accessibleName == null;\n\n const visual = (\n <span\n ref={ref}\n id={id}\n data-testid={testId}\n className={cn(\n featureIconVariants({ size, background, corners, animated }),\n className,\n )}\n role={decorative ? undefined : 'img'}\n aria-label={decorative ? undefined : accessibleName}\n aria-hidden={decorative ? ariaHidden ?? true : ariaHidden}\n >\n {resolvedIcon}\n </span>\n );\n\n if (tooltip == null) {\n return visual;\n }\n\n // Focusable makes the non-interactive icon a valid, keyboard-reachable\n // tooltip trigger without turning it into a button.\n return (\n <Tooltip>\n <TooltipTrigger>\n <Focusable>{visual}</Focusable>\n </TooltipTrigger>\n <TooltipContent side={tooltipSide}>{tooltip}</TooltipContent>\n </Tooltip>\n );\n },\n);\n\nFeatureIcon.displayName = 'FeatureIcon';\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode } from 'react';\n\n/**\n * FeatureIcon — a display-only icon inside a styled rounded container.\n *\n * Non-interactive by design (no onPress / href). It communicates a feature,\n * section, or status visually. When `tooltip` is provided it becomes a\n * keyboard-focusable, AT-named element wrapped in the Themis Tooltip.\n *\n * @see constitution.md Principle IV (Accessibility First — WCAG 2.2 AAA target)\n */\n\n/** Container / icon size scale. */\nexport const FeatureIconSizeSchema = z.enum(['sm', 'default', 'lg', 'xl']);\nexport type FeatureIconSize = z.infer<typeof FeatureIconSizeSchema>;\n\n/**\n * Background treatment of the container.\n * - transparent: no fill, brand-coloured icon\n * - primary: solid brand\n * - pale: light brand tint\n * - dark: deep brand (--primary-800)\n * - status: informational status surface\n * - sidekick: Sidekick AI gradient\n */\nexport const FeatureIconBackgroundSchema = z.enum([\n 'transparent',\n 'primary',\n 'pale',\n 'dark',\n 'status',\n 'sidekick',\n]);\nexport type FeatureIconBackground = z.infer<typeof FeatureIconBackgroundSchema>;\n\n/** Corner radius treatment. */\nexport const FeatureIconCornersSchema = z.enum(['square', 'rounded', 'full']);\nexport type FeatureIconCorners = z.infer<typeof FeatureIconCornersSchema>;\n\n/**\n * Predefined section icons (set by design guidelines).\n * Extend this list as new product sections are standardised.\n */\nexport const FeatureIconSectionSchema = z.enum([\n 'jobs',\n 'candidates',\n 'interviews',\n 'messages',\n 'reports',\n 'tasks',\n 'settings',\n 'notifications',\n]);\nexport type FeatureIconSection = z.infer<typeof FeatureIconSectionSchema>;\n\nexport const FeatureIconPropsSchema = BaseComponentPropsSchema.extend({\n /** Container/icon size (default 'default'). */\n size: FeatureIconSizeSchema.optional(),\n /** Background treatment (default 'primary'). */\n background: FeatureIconBackgroundSchema.optional(),\n /** Corner radius (default 'rounded'). */\n corners: FeatureIconCornersSchema.optional(),\n /** Predefined section icon (per guidelines). Overridden by `icon`. */\n section: FeatureIconSectionSchema.optional(),\n /** Custom icon node. Takes precedence over `section`. */\n icon: z.custom<ReactNode>().optional(),\n /** Subtle idle animation (honours prefers-reduced-motion). */\n animated: z.boolean().optional(),\n /** When set, wraps the icon in a tooltip with this text and names it for AT. */\n tooltip: z.string().optional(),\n /** Tooltip placement (default 'top'). */\n tooltipSide: z.enum(['top', 'bottom', 'left', 'right']).optional(),\n});\n\n/**\n * Explicit interface — avoids Zod 4 d.ts inference issues where optional\n * fields can resolve as required through complex generics.\n */\nexport interface FeatureIconProps {\n className?: string;\n id?: string;\n 'data-testid'?: string;\n 'aria-label'?: string;\n 'aria-hidden'?: boolean;\n size?: FeatureIconSize;\n background?: FeatureIconBackground;\n corners?: FeatureIconCorners;\n /** Predefined section icon (per guidelines). Overridden by `icon`. */\n section?: FeatureIconSection;\n /** Custom icon node. Takes precedence over `section`. */\n icon?: ReactNode;\n /** Subtle idle animation (honours prefers-reduced-motion). */\n animated?: boolean;\n /** When set, wraps the icon in a tooltip with this text and names it for AT. */\n tooltip?: string;\n /** Tooltip placement (default 'top'). */\n tooltipSide?: 'top' | 'bottom' | 'left' | 'right';\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {forwardRef}from'react';import {Focusable,TooltipTrigger,Tooltip,OverlayArrow,composeRenderProps}from'react-aria-components';import {Bell,Settings,ListChecks,ChartColumn,MessageSquare,CalendarDays,Users,Briefcase}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {z as z$1}from'zod';function g(...e){return twMerge(clsx(e))}var F=cva(["z-50 overflow-hidden rounded-md px-3 py-1.5 text-sm","bg-[var(--content-foreground)] text-[var(--content-background)]","motion-safe:animate-in motion-safe:fade-in-0","data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0"],{variants:{side:{top:["motion-safe:slide-in-from-bottom-2","data-[exiting]:motion-safe:slide-out-to-bottom-2"],bottom:["motion-safe:slide-in-from-top-2","data-[exiting]:motion-safe:slide-out-to-top-2"],left:["motion-safe:slide-in-from-right-2","data-[exiting]:motion-safe:slide-out-to-right-2"],right:["motion-safe:slide-in-from-left-2","data-[exiting]:motion-safe:slide-out-to-left-2"]}},defaultVariants:{side:"top"}}),S=cva("fill-[var(--content-foreground)]",{variants:{side:{top:"rotate-180",bottom:"rotate-0",left:"rotate-90",right:"-rotate-90"}},defaultVariants:{side:"top"}});function I(e){if(!e)return "top";let t=e.split(" ")[0];return t==="top"||t==="bottom"||t==="left"||t==="right"?t:"top"}function L({children:e,delay:t=700,closeDelay:i=300,trigger:s="hover",isOpen:c,defaultOpen:d=false,onOpenChange:p,isDisabled:u=false}){return jsx(TooltipTrigger,{delay:s==="focus"?99999999:t,closeDelay:i,isOpen:c,defaultOpen:d,onOpenChange:p,isDisabled:u,children:e})}L.displayName="Tooltip";function D({children:e}){return e}D.displayName="TooltipTrigger";function R({children:e,side:t="top",sideOffset:i=4,alignOffset:s=0,shouldFlip:c=true,showArrow:d=false,arrowSize:p=8,className:u,...f}){return jsx(Tooltip,{placement:t,offset:i,crossOffset:s,shouldFlip:c,...f,className:composeRenderProps(u,(l,m)=>{let x=I(m.placement);return g(F({side:x}),l)}),children:l=>{let m=I(l.placement);return jsxs(Fragment,{children:[d&&jsx(OverlayArrow,{children:jsx("svg",{width:p,height:p,viewBox:"0 0 8 8",className:S({side:m}),"data-testid":"tooltip-arrow",children:jsx("path",{d:"M0 0 L4 4 L8 0"})})}),e]})}})}R.displayName="TooltipContent";var _=L,h=D,v=R;var w=z$1.object({className:z$1.string().optional(),children:z$1.any().optional(),id:z$1.string().optional(),"aria-label":z$1.string().optional(),"aria-labelledby":z$1.string().optional(),"aria-describedby":z$1.string().optional(),"aria-live":z$1.enum(["off","polite","assertive"]).optional(),"aria-hidden":z$1.boolean().optional(),"data-testid":z$1.string().optional()});var M=["focus-visible:outline-none","focus-visible:ring-2","focus-visible:ring-[var(--ring)]","focus-visible:ring-offset-2"];var P=["motion-reduce:transition-none","motion-reduce:animate-none"],k=["transition-colors","duration-200"];function B(...e){return e.flatMap(t=>Array.isArray(t)?[...t]:[t])}var O=cva(B("inline-flex shrink-0 items-center justify-center overflow-hidden",M,k,P),{variants:{size:{sm:"h-8 w-8 [&_svg]:size-4",default:"h-10 w-10 [&_svg]:size-5",lg:"h-12 w-12 [&_svg]:size-6",xl:"h-16 w-16 [&_svg]:size-8"},background:{transparent:"bg-transparent text-[var(--primary)]",primary:"bg-[var(--primary)] text-[var(--primary-foreground)]",pale:"bg-[var(--primary-100)] text-[var(--primary-700)]",dark:"bg-[var(--primary-800)] text-[var(--primary-foreground)]",status:"bg-[var(--info-background)] text-[var(--info-foreground)]",sidekick:"bg-gradient-to-br from-[var(--primary-400)] via-[var(--primary)] to-[var(--primary-700)] text-[var(--primary-foreground)]"},corners:{square:"rounded-none",rounded:"rounded-lg",full:"rounded-full"},animated:{true:"[&_svg]:feature-icon-animated [&_svg]:motion-reduce:animate-none",false:""}},defaultVariants:{size:"default",background:"pale",corners:"rounded",animated:false}});var ut={jobs:jsx(Briefcase,{"aria-hidden":"true"}),candidates:jsx(Users,{"aria-hidden":"true"}),interviews:jsx(CalendarDays,{"aria-hidden":"true"}),messages:jsx(MessageSquare,{"aria-hidden":"true"}),reports:jsx(ChartColumn,{"aria-hidden":"true"}),tasks:jsx(ListChecks,{"aria-hidden":"true"}),settings:jsx(Settings,{"aria-hidden":"true"}),notifications:jsx(Bell,{"aria-hidden":"true"})},z=forwardRef(function({className:t,id:i,size:s,background:c,corners:d,section:p,icon:u,animated:f,tooltip:l,tooltipSide:m="top","aria-label":x,"aria-hidden":E,"data-testid":Z="feature-icon"},q){let $=u??(p?ut[p]:null),b=x??l,T=b==null,y=jsx("span",{ref:q,id:i,"data-testid":Z,className:g(O({size:s,background:c,corners:d,animated:f}),t),role:T?void 0:"img","aria-label":T?void 0:b,"aria-hidden":T?E??true:E,children:$});return l==null?y:jsxs(_,{children:[jsx(h,{children:jsx(Focusable,{children:y})}),jsx(v,{side:m,children:l})]})});z.displayName="FeatureIcon";var U=z$1.enum(["sm","default","lg","xl"]),V=z$1.enum(["transparent","primary","pale","dark","status","sidekick"]),G=z$1.enum(["square","rounded","full"]),H=z$1.enum(["jobs","candidates","interviews","messages","reports","tasks","settings","notifications"]),gt=w.extend({size:U.optional(),background:V.optional(),corners:G.optional(),section:H.optional(),icon:z$1.custom().optional(),animated:z$1.boolean().optional(),tooltip:z$1.string().optional(),tooltipSide:z$1.enum(["top","bottom","left","right"]).optional()});export{z as FeatureIcon,V as FeatureIconBackgroundSchema,G as FeatureIconCornersSchema,gt as FeatureIconPropsSchema,H as FeatureIconSectionSchema,U as FeatureIconSizeSchema,O as featureIconVariants};//# sourceMappingURL=index.mjs.map
|
|
3
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Tooltip/Tooltip.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/styles/shared-variants.ts","../../../src/elements/FeatureIcon/FeatureIcon.styles.ts","../../../src/elements/FeatureIcon/FeatureIcon.tsx","../../../src/elements/FeatureIcon/FeatureIcon.types.ts"],"names":["cn","inputs","twMerge","clsx","tooltipContentVariants","cva","tooltipArrowVariants","placementToSide","placement","basePlacement","TooltipRoot","children","delay","closeDelay","trigger","isOpen","defaultOpen","onOpenChange","isDisabled","jsx","AriaTooltipTrigger","TooltipTriggerComponent","TooltipContentComponent","side","sideOffset","alignOffset","shouldFlip","showArrow","arrowSize","className","restProps","AriaTooltip","composeRenderProps","renderProps","actualSide","jsxs","Fragment","OverlayArrow","Tooltip","TooltipTrigger","TooltipContent","BaseComponentPropsSchema","z","FOCUS_VISIBLE_RING","REDUCED_MOTION","TRANSITION_COLORS","combineStyles","styles","s","featureIconVariants","SECTION_ICONS","Briefcase","Users","CalendarDays","MessageSquare","ChartColumn","ListChecks","Settings","Bell","FeatureIcon","forwardRef","id","size","background","corners","section","icon","animated","tooltip","tooltipSide","ariaLabel","ariaHidden","testId","ref","resolvedIcon","accessibleName","decorative","visual","Focusable","FeatureIconSizeSchema","FeatureIconBackgroundSchema","FeatureIconCornersSchema","FeatureIconSectionSchema","FeatureIconPropsSchema"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Tooltip Component - Implementation\n *\n * Accessible tooltip component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure.\n *\n * @see plan.md (Implementation plan)\n * @see Tooltip.types.ts (Zod schemas)\n * @see tooltip-prd.md (Full requirements)\n */\n\nimport { type ReactElement } from 'react';\nimport {\n TooltipTrigger as AriaTooltipTrigger,\n Tooltip as AriaTooltip,\n OverlayArrow,\n composeRenderProps,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport type {\n TooltipProps,\n TooltipTriggerProps,\n TooltipContentProps,\n TooltipArrowProps,\n TooltipSide,\n} from './Tooltip.types';\n\n/**\n * CVA Variants for TooltipContent\n *\n * Placement-based animations and high-contrast inverted colors.\n *\n * @see plan.md (CVA Variant Structure)\n * @see tooltip-prd.md US-2 (Configurable Placement)\n */\nexport const tooltipContentVariants = cva(\n // Base styles\n [\n \"z-50 overflow-hidden rounded-md px-3 py-1.5 text-sm\",\n // Inverted colors for high contrast (7:1 ratio)\n \"bg-[var(--content-foreground)] text-[var(--content-background)]\",\n // Entry animation base (motion-safe guarded)\n \"motion-safe:animate-in motion-safe:fade-in-0\",\n // Exit animation\n \"data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0\",\n ],\n {\n variants: {\n side: {\n top: [\n \"motion-safe:slide-in-from-bottom-2\",\n \"data-[exiting]:motion-safe:slide-out-to-bottom-2\",\n ],\n bottom: [\n \"motion-safe:slide-in-from-top-2\",\n \"data-[exiting]:motion-safe:slide-out-to-top-2\",\n ],\n left: [\n \"motion-safe:slide-in-from-right-2\",\n \"data-[exiting]:motion-safe:slide-out-to-right-2\",\n ],\n right: [\n \"motion-safe:slide-in-from-left-2\",\n \"data-[exiting]:motion-safe:slide-out-to-left-2\",\n ],\n },\n },\n defaultVariants: {\n side: \"top\",\n },\n }\n);\n\n/**\n * CVA Variants for TooltipArrow\n *\n * Rotation based on placement for correct arrow pointing direction.\n *\n * @see tooltip-prd.md US-2 (Arrow Indicator)\n */\nexport const tooltipArrowVariants = cva(\n // Base arrow styles\n \"fill-[var(--content-foreground)]\",\n {\n variants: {\n side: {\n top: \"rotate-180\",\n bottom: \"rotate-0\",\n left: \"rotate-90\",\n right: \"-rotate-90\",\n },\n },\n defaultVariants: {\n side: \"top\",\n },\n }\n);\n\n/**\n * Map React Aria placement to our side prop\n * React Aria uses placement prop with values like 'top', 'bottom', etc.\n * PlacementAxis can be 'top' | 'bottom' | 'left' | 'right' | null\n */\nfunction placementToSide(placement: string | null | undefined): TooltipSide {\n if (!placement) return 'top';\n // Extract the base placement (e.g., 'top start' -> 'top')\n const basePlacement = placement.split(' ')[0];\n if (basePlacement === 'top' || basePlacement === 'bottom' ||\n basePlacement === 'left' || basePlacement === 'right') {\n return basePlacement;\n }\n return 'top';\n}\n\n/**\n * Tooltip Root Component\n *\n * Manages tooltip open/close state, delays, and trigger behavior.\n * Wraps React Aria's TooltipTrigger with delay configuration.\n *\n * @see tooltip-prd.md US-1 (Basic Usage)\n * @see tooltip-prd.md US-3 (Delay Configuration)\n * @see tooltip-prd.md US-7 (Controlled State)\n */\nfunction TooltipRoot({\n children,\n delay = 700,\n closeDelay = 300,\n trigger = 'hover',\n isOpen,\n defaultOpen = false,\n onOpenChange,\n isDisabled = false,\n}: TooltipProps): ReactElement {\n // React Aria doesn't have a direct trigger mode prop\n // 'focus' mode is achieved by setting delay to a very high value\n // and relying on focus to trigger immediately\n const effectiveDelay = trigger === 'focus' ? 99999999 : delay;\n\n return (\n <AriaTooltipTrigger\n delay={effectiveDelay}\n closeDelay={closeDelay}\n isOpen={isOpen}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n isDisabled={isDisabled}\n >\n {children}\n </AriaTooltipTrigger>\n );\n}\n\nTooltipRoot.displayName = 'Tooltip';\n\n/**\n * TooltipTrigger Component\n *\n * Wrapper for the element that triggers the tooltip.\n * The child element must be focusable (or wrapped with Focusable).\n *\n * React Aria's TooltipTrigger automatically applies:\n * - aria-describedby linking to tooltip\n * - Hover and focus event handlers\n *\n * @see tooltip-prd.md US-5 (Non-Button Triggers)\n */\nfunction TooltipTriggerComponent({\n children,\n}: TooltipTriggerProps): ReactElement {\n // React Aria's TooltipTrigger expects the trigger element as a direct child\n // We pass through the child element directly\n return children as ReactElement;\n}\n\nTooltipTriggerComponent.displayName = 'TooltipTrigger';\n\n/**\n * TooltipContent Component\n *\n * The actual tooltip overlay that appears.\n * Supports placement, offset, and optional arrow.\n *\n * @see tooltip-prd.md US-2 (Placement and Arrow)\n * @see tooltip-prd.md Technical Implementation Details\n */\nfunction TooltipContentComponent({\n children,\n side = 'top',\n sideOffset = 4,\n alignOffset = 0,\n shouldFlip = true,\n showArrow = false,\n arrowSize = 8,\n className,\n ...restProps\n}: TooltipContentProps & { 'data-testid'?: string }): ReactElement {\n return (\n <AriaTooltip\n placement={side}\n offset={sideOffset}\n crossOffset={alignOffset}\n shouldFlip={shouldFlip}\n {...restProps}\n className={composeRenderProps(className, (className, renderProps) => {\n // Get actual placement from render props for animation direction\n const actualSide = placementToSide(renderProps.placement);\n return cn(\n tooltipContentVariants({ side: actualSide }),\n className\n );\n })}\n >\n {(renderProps) => {\n const actualSide = placementToSide(renderProps.placement);\n return (\n <>\n {showArrow && (\n <OverlayArrow>\n <svg\n width={arrowSize}\n height={arrowSize}\n viewBox=\"0 0 8 8\"\n className={tooltipArrowVariants({ side: actualSide })}\n data-testid=\"tooltip-arrow\"\n >\n <path d=\"M0 0 L4 4 L8 0\" />\n </svg>\n </OverlayArrow>\n )}\n {children}\n </>\n );\n }}\n </AriaTooltip>\n );\n}\n\nTooltipContentComponent.displayName = 'TooltipContent';\n\n/**\n * TooltipArrow Component\n *\n * Optional arrow component for custom arrow rendering.\n * Automatically positioned based on tooltip placement.\n *\n * Note: This is an alternative to using showArrow prop on TooltipContent.\n * Use this when you need custom arrow styling or rendering.\n *\n * @see tooltip-prd.md US-2 (Arrow Indicator)\n */\nfunction TooltipArrowComponent({\n size = 8,\n className,\n 'data-testid': dataTestId = 'tooltip-arrow',\n ...restProps\n}: TooltipArrowProps & { 'data-testid'?: string }): ReactElement {\n // This component is designed to be used inside TooltipContent\n // The actual positioning is handled by OverlayArrow from React Aria\n return (\n <OverlayArrow>\n {({ placement }) => {\n const side = placementToSide(placement);\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 8 8\"\n className={cn(tooltipArrowVariants({ side }), className)}\n data-testid={dataTestId}\n {...restProps}\n >\n <path d=\"M0 0 L4 4 L8 0\" />\n </svg>\n );\n }}\n </OverlayArrow>\n );\n}\n\nTooltipArrowComponent.displayName = 'TooltipArrow';\n\n/**\n * Export all components\n *\n * Following Themis pattern - export individual components\n * No Object.assign compound pattern for Tooltip since React Aria\n * expects specific component hierarchy.\n */\nexport const Tooltip = TooltipRoot;\nexport const TooltipTrigger = TooltipTriggerComponent;\nexport const TooltipContent = TooltipContentComponent;\nexport const TooltipArrow = TooltipArrowComponent;\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva } from 'class-variance-authority';\nimport {\n combineStyles,\n FOCUS_VISIBLE_RING,\n REDUCED_MOTION,\n TRANSITION_COLORS,\n} from '../../styles/shared-variants';\n\n/**\n * FeatureIcon container variants.\n *\n * Sizing also scales the inner SVG via `[&_svg]:size-*`, so any lucide / svg\n * icon passed in is sized consistently without per-icon props.\n *\n * Colour values come from the Themis primary scale + semantic tokens:\n * pale -> --primary-100, dark -> --primary-800, status -> --info-*, and the\n * sidekick gradient ramps across the primary scale.\n */\nexport const featureIconVariants = cva(\n combineStyles(\n 'inline-flex shrink-0 items-center justify-center overflow-hidden',\n FOCUS_VISIBLE_RING,\n TRANSITION_COLORS,\n REDUCED_MOTION,\n ),\n {\n variants: {\n size: {\n sm: 'h-8 w-8 [&_svg]:size-4',\n default: 'h-10 w-10 [&_svg]:size-5',\n lg: 'h-12 w-12 [&_svg]:size-6',\n xl: 'h-16 w-16 [&_svg]:size-8',\n },\n background: {\n transparent: 'bg-transparent text-[var(--primary)]',\n primary: 'bg-[var(--primary)] text-[var(--primary-foreground)]',\n pale: 'bg-[var(--primary-100)] text-[var(--primary-700)]',\n dark: 'bg-[var(--primary-800)] text-[var(--primary-foreground)]',\n status: 'bg-[var(--info-background)] text-[var(--info-foreground)]',\n sidekick:\n 'bg-gradient-to-br from-[var(--primary-400)] via-[var(--primary)] to-[var(--primary-700)] text-[var(--primary-foreground)]',\n },\n corners: {\n square: 'rounded-none',\n rounded: 'rounded-lg',\n full: 'rounded-full',\n },\n animated: {\n // Animates the inner icon (svg), not the container.\n true: '[&_svg]:feature-icon-animated [&_svg]:motion-reduce:animate-none',\n false: '',\n },\n },\n defaultVariants: {\n size: 'default',\n background: 'pale',\n corners: 'rounded',\n animated: false,\n },\n },\n);\n","'use client';\n\n/**\n * FeatureIcon Component\n *\n * A display-only icon inside a styled, rounded container. Non-interactive by\n * design — it does not handle clicks or navigation. Use it to represent a\n * feature, product section, or status.\n *\n * Accessibility:\n * - Purely decorative by default (aria-hidden) so it adds no screen-reader noise.\n * - Give it meaning with `aria-label` and/or `tooltip`; it then exposes\n * role=\"img\" with an accessible name.\n * - When `tooltip` is set the icon becomes keyboard-focusable (via React Aria\n * Focusable) and uses the Themis Tooltip, which is hoverable + dismissible\n * (WCAG 1.4.13).\n *\n * @see constitution.md Principle IV (Accessibility First)\n */\n\nimport { forwardRef, type ReactNode } from 'react';\nimport { Focusable } from 'react-aria-components';\nimport {\n Bell,\n Briefcase,\n CalendarDays,\n ChartColumn,\n ListChecks,\n MessageSquare,\n Settings,\n Users,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip';\nimport { featureIconVariants } from './FeatureIcon.styles';\nimport type { FeatureIconProps, FeatureIconSection } from './FeatureIcon.types';\n\n/**\n * Section → icon map (set by design guidelines).\n * Extend alongside FeatureIconSectionSchema as sections are standardised.\n */\nconst SECTION_ICONS: Record<FeatureIconSection, ReactNode> = {\n jobs: <Briefcase aria-hidden=\"true\" />,\n candidates: <Users aria-hidden=\"true\" />,\n interviews: <CalendarDays aria-hidden=\"true\" />,\n messages: <MessageSquare aria-hidden=\"true\" />,\n reports: <ChartColumn aria-hidden=\"true\" />,\n tasks: <ListChecks aria-hidden=\"true\" />,\n settings: <Settings aria-hidden=\"true\" />,\n notifications: <Bell aria-hidden=\"true\" />,\n};\n\nexport const FeatureIcon = forwardRef<HTMLSpanElement, FeatureIconProps>(\n function FeatureIcon(\n {\n className,\n id,\n size,\n background,\n corners,\n section,\n icon,\n animated,\n tooltip,\n tooltipSide = 'top',\n 'aria-label': ariaLabel,\n 'aria-hidden': ariaHidden,\n 'data-testid': testId = 'feature-icon',\n },\n ref,\n ) {\n // Icon precedence: custom `icon` > `section` > none.\n const resolvedIcon: ReactNode = icon ?? (section ? SECTION_ICONS[section] : null);\n\n // Accessible name: explicit aria-label wins, otherwise the tooltip text.\n const accessibleName = ariaLabel ?? tooltip;\n const decorative = accessibleName == null;\n\n const visual = (\n <span\n ref={ref}\n id={id}\n data-testid={testId}\n className={cn(\n featureIconVariants({ size, background, corners, animated }),\n className,\n )}\n role={decorative ? undefined : 'img'}\n aria-label={decorative ? undefined : accessibleName}\n aria-hidden={decorative ? ariaHidden ?? true : ariaHidden}\n >\n {resolvedIcon}\n </span>\n );\n\n if (tooltip == null) {\n return visual;\n }\n\n // Focusable makes the non-interactive icon a valid, keyboard-reachable\n // tooltip trigger without turning it into a button.\n return (\n <Tooltip>\n <TooltipTrigger>\n <Focusable>{visual}</Focusable>\n </TooltipTrigger>\n <TooltipContent side={tooltipSide}>{tooltip}</TooltipContent>\n </Tooltip>\n );\n },\n);\n\nFeatureIcon.displayName = 'FeatureIcon';\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode } from 'react';\n\n/**\n * FeatureIcon — a display-only icon inside a styled rounded container.\n *\n * Non-interactive by design (no onPress / href). It communicates a feature,\n * section, or status visually. When `tooltip` is provided it becomes a\n * keyboard-focusable, AT-named element wrapped in the Themis Tooltip.\n *\n * @see constitution.md Principle IV (Accessibility First — WCAG 2.2 AAA target)\n */\n\n/** Container / icon size scale. */\nexport const FeatureIconSizeSchema = z.enum(['sm', 'default', 'lg', 'xl']);\nexport type FeatureIconSize = z.infer<typeof FeatureIconSizeSchema>;\n\n/**\n * Background treatment of the container.\n * - transparent: no fill, brand-coloured icon\n * - primary: solid brand\n * - pale: light brand tint\n * - dark: deep brand (--primary-800)\n * - status: informational status surface\n * - sidekick: Sidekick AI gradient\n */\nexport const FeatureIconBackgroundSchema = z.enum([\n 'transparent',\n 'primary',\n 'pale',\n 'dark',\n 'status',\n 'sidekick',\n]);\nexport type FeatureIconBackground = z.infer<typeof FeatureIconBackgroundSchema>;\n\n/** Corner radius treatment. */\nexport const FeatureIconCornersSchema = z.enum(['square', 'rounded', 'full']);\nexport type FeatureIconCorners = z.infer<typeof FeatureIconCornersSchema>;\n\n/**\n * Predefined section icons (set by design guidelines).\n * Extend this list as new product sections are standardised.\n */\nexport const FeatureIconSectionSchema = z.enum([\n 'jobs',\n 'candidates',\n 'interviews',\n 'messages',\n 'reports',\n 'tasks',\n 'settings',\n 'notifications',\n]);\nexport type FeatureIconSection = z.infer<typeof FeatureIconSectionSchema>;\n\nexport const FeatureIconPropsSchema = BaseComponentPropsSchema.extend({\n /** Container/icon size (default 'default'). */\n size: FeatureIconSizeSchema.optional(),\n /** Background treatment (default 'primary'). */\n background: FeatureIconBackgroundSchema.optional(),\n /** Corner radius (default 'rounded'). */\n corners: FeatureIconCornersSchema.optional(),\n /** Predefined section icon (per guidelines). Overridden by `icon`. */\n section: FeatureIconSectionSchema.optional(),\n /** Custom icon node. Takes precedence over `section`. */\n icon: z.custom<ReactNode>().optional(),\n /** Subtle idle animation (honours prefers-reduced-motion). */\n animated: z.boolean().optional(),\n /** When set, wraps the icon in a tooltip with this text and names it for AT. */\n tooltip: z.string().optional(),\n /** Tooltip placement (default 'top'). */\n tooltipSide: z.enum(['top', 'bottom', 'left', 'right']).optional(),\n});\n\n/**\n * Explicit interface — avoids Zod 4 d.ts inference issues where optional\n * fields can resolve as required through complex generics.\n */\nexport interface FeatureIconProps {\n className?: string;\n id?: string;\n 'data-testid'?: string;\n 'aria-label'?: string;\n 'aria-hidden'?: boolean;\n size?: FeatureIconSize;\n background?: FeatureIconBackground;\n corners?: FeatureIconCorners;\n /** Predefined section icon (per guidelines). Overridden by `icon`. */\n section?: FeatureIconSection;\n /** Custom icon node. Takes precedence over `section`. */\n icon?: ReactNode;\n /** Subtle idle animation (honours prefers-reduced-motion). */\n animated?: boolean;\n /** When set, wraps the icon in a tooltip with this text and names it for AT. */\n tooltip?: string;\n /** Tooltip placement (default 'top'). */\n tooltipSide?: 'top' | 'bottom' | 'left' | 'right';\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function b(...e){return tailwindMerge.twMerge(clsx.clsx(e))}var me=classVarianceAuthority.cva("inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",{variants:{fullWidth:{true:"w-full",false:""},inVerticalGroup:{true:"items-stretch",false:"items-center"}},defaultVariants:{fullWidth:false,inVerticalGroup:false}}),ge=classVarianceAuthority.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-normal ring-offset-background motion-safe:transition-transform motion-safe:duration-200 motion-safe:[transition-timing-function:cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer",{variants:{variant:{default:"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] hover:-translate-y-1",destructive:"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] hover:bg-[var(--destructive-background-hover,var(--destructive-background))] motion-safe:hover:btn-warn-shake",outline:"border border-[var(--input-border)] bg-[var(--page-background)] hover:bg-[var(--input-border)]",secondary:"bg-[var(--secondary)] text-[var(--secondary-foreground)] hover:bg-[var(--secondary-hover,var(--secondary))]",ghost:"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]",link:"text-[var(--text-link)] underline underline-offset-4 hover:bg-[var(--accent)] hover:text-[var(--text-link-hover)]"},fullWidth:{true:"w-full",false:""},visualSize:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3 text-xs",lg:"h-11 rounded-md px-6 text-base",icon:"h-10 w-10",dot:"h-5 w-5 rounded-full p-0 min-h-0 min-w-0"},paywall:{true:"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent",false:""}},defaultVariants:{variant:"default",visualSize:"default",paywall:false}});var ve="data-[pressed]:scale-[0.97]";var te="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",re="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var dt=react.createContext(null);dt.displayName="ButtonGroupContext";function ut(){return react.useContext(dt)}var ct=react.createContext(null);ct.displayName="ButtonGroupItemContext";function ft(){return react.useContext(ct)}classVarianceAuthority.cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}});var pt=classVarianceAuthority.cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}});classVarianceAuthority.cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var D=react.memo(react.forwardRef(({className:e,buttonVisualClassName:r,variant:t,size:a,visualSize:i,fullWidth:o,loading:d=false,loadingText:m="Loading...",shortcut:u,children:c,isDisabled:g,paywall:s=false,paywallRedirect:h,paywallDescription:V,onPress:f,...I},de)=>{let Y=react.useId(),v=ut(),N=ft(),B=t??v?.variant??"default",ue=a??v?.size,U=g??v?.isDisabled??false,X=v?.orientation==="vertical",q=o||X,ce=N?pt({orientation:v?.orientation??"horizontal",position:N.position}):"",M=i??ue??"default";return process.env.NODE_ENV!=="production"&&(M==="dot"||M==="icon")&&!I["aria-label"]&&!c&&console.warn('[Button] visualSize="dot" or "icon" requires aria-label when no visible text is provided (WCAG 1.1.1)'),jsxRuntime.jsx(reactAriaComponents.Button,{ref:de,isDisabled:U||d||void 0,"aria-disabled":s?true:void 0,"aria-describedby":s?Y:void 0,onPress:R=>{if(s){h&&window.open(h,"_blank","noopener,noreferrer");return}f?.(R);},className:b(me({fullWidth:q,inVerticalGroup:X}),e),...I,children:R=>jsxRuntime.jsxs("span",{className:b(ge({variant:B,visualSize:M,paywall:s,fullWidth:q}),ce,r,ve,"",te,re),"data-pressed":R.isPressed||void 0,children:[d&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"motion-safe:animate-spin","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"sr-only","aria-live":"polite",children:m})]}),!d&&c,s&&jsxRuntime.jsx(lucideReact.Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),s&&jsxRuntime.jsxs("span",{id:Y,className:"sr-only",children:["Premium feature: ",V||"Upgrade required to access this feature"]}),R.isFocusVisible&&u&&jsxRuntime.jsx("kbd",{className:"ml-auto hidden text-xs opacity-60 lg:inline",children:u})]})})}));D.displayName="Button";var Ee=["focus-within:outline-none","focus-within:ring-2","focus-within:ring-[var(--ring)]","focus-within:ring-offset-2"],he=["focus-visible:outline-none","focus-visible:ring-2","focus-visible:ring-[var(--ring)]","focus-visible:ring-offset-2"];var Ie=["disabled:pointer-events-none","disabled:opacity-50"];var w={sm:"text-xs",default:"text-sm",lg:"text-base"},ie={sm:"text-sm",default:"text-base",lg:"text-lg"},ne=["min-h-[44px]","min-w-[44px]"];var Fe=["flex","items-center","gap-1.5","text-[var(--destructive-background)]"],_e=["flex","items-center","gap-1.5","text-[var(--success-background)]"],Te=["text-[var(--menu-muted)]"],Ve=["font-medium","text-[var(--content-foreground)]"];var oe=["transition-colors","duration-200"];function O(...e){return e.flatMap(r=>Array.isArray(r)?[...r]:[r])}var Ne=classVarianceAuthority.cva("flex flex-col gap-1.5 w-full",{variants:{size:ie},defaultVariants:{size:"default"}}),ye=classVarianceAuthority.cva(O("flex flex-col items-center justify-center rounded-md border-2 border-dashed","bg-[var(--content-background)] text-[var(--content-foreground)]",oe,Ee),{variants:{size:{sm:"min-h-[100px] p-4 gap-2",default:"min-h-[140px] p-6 gap-3",lg:"min-h-[180px] p-8 gap-4"},isDragOver:{true:"border-[var(--primary)] bg-[var(--primary)]/5",false:"border-[var(--input-border)] hover:border-[var(--primary)]/50"},isInvalid:{true:"border-[var(--destructive-background)] bg-[var(--destructive-background)]/5",false:""},isDisabled:{true:"opacity-50 cursor-not-allowed pointer-events-none",false:"cursor-pointer"}},compoundVariants:[{isInvalid:true,isDragOver:true,className:"border-[var(--destructive-background)] bg-[var(--destructive-background)]/5"}],defaultVariants:{size:"default",isDragOver:false,isInvalid:false,isDisabled:false}}),Pe=classVarianceAuthority.cva(O("inline-flex items-center justify-center gap-2 rounded-md font-medium",oe,ne,he,Ie),{variants:{size:{sm:"px-3 py-2 text-xs",default:"px-4 py-2 text-sm",lg:"px-6 py-3 text-base"},variant:{default:"bg-[var(--primary)] text-[var(--primary-foreground)] hover:bg-[var(--primary)]/90",outline:"border border-[var(--input-border)] bg-transparent hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]"}},defaultVariants:{size:"default",variant:"default"}}),Re=classVarianceAuthority.cva("flex flex-col gap-2 mt-3",{variants:{size:{sm:"gap-1.5",default:"gap-2",lg:"gap-3"}},defaultVariants:{size:"default"}}),mt=classVarianceAuthority.cva("flex items-center justify-between mb-1",{variants:{size:w},defaultVariants:{size:"default"}}),Oe=classVarianceAuthority.cva("flex items-center justify-between gap-3 bg-[var(--accent-background)] rounded-md border border-[var(--border)]",{variants:{size:{sm:"px-2 py-1.5 text-xs",default:"px-3 py-2 text-sm",lg:"px-4 py-3 text-base"}},defaultVariants:{size:"default"}}),Ae=classVarianceAuthority.cva(O("inline-flex items-center justify-center rounded-full",ne,"-mr-2 -my-1","text-[var(--menu-muted)] hover:text-[var(--destructive-background)] hover:bg-[var(--destructive-background)]/10","transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]"),{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),Le=classVarianceAuthority.cva(O(Fe,"font-medium"),{variants:{size:w},defaultVariants:{size:"default"}}),De=classVarianceAuthority.cva(O(_e,"font-medium"),{variants:{size:w},defaultVariants:{size:"default"}}),we=classVarianceAuthority.cva(Te,{variants:{size:w},defaultVariants:{size:"default"}}),Ce=classVarianceAuthority.cva(Ve,{variants:{size:ie,isRequired:{true:"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]",false:""}},defaultVariants:{size:"default",isRequired:false}});function se(e){if(e===0)return "0 B";let r=1024,t=["B","KB","MB","GB"],a=Math.floor(Math.log(e)/Math.log(r)),i=parseFloat((e/Math.pow(r,a)).toFixed(1));return `${i%1===0?i.toFixed(0):i.toFixed(1)} ${t[a]}`}function $(e,r=30){if(e.length<=r)return e;let t=e.lastIndexOf(".");if(t===-1)return `${e.slice(0,r-3)}...`;let a=e.slice(t),i=e.slice(0,t),o=r-a.length-3;return o<1?`...${a}`:`${i.slice(0,o)}...${a}`}function Be(e,r){return !r||r.length===0?true:r.some(t=>{if(t.endsWith("/*")){let a=t.slice(0,-2);return e.type.startsWith(`${a}/`)}return t.includes("/")?e.type===t:t.startsWith(".")?e.name.toLowerCase().endsWith(t.toLowerCase()):false})}function j(e){return e.type.startsWith("image/")?"image":e.type.startsWith("video/")?"video":e.type.startsWith("audio/")?"audio":"file"}function W(e,r){let t=[...e];for(let a of r){let i=t.findIndex(o=>o.name===a.name);i>=0?t[i]=a:t.push(a);}return t}function Zt(e){return !e||e.length===0?"any file":e.map(t=>t==="image/*"?"images":t==="video/*"?"videos":t==="audio/*"?"audio":t.startsWith(".")?t.slice(1).toUpperCase():t.includes("/")?(t.split("/")[1]??t).toUpperCase():t).join(", ")}var gt=2*1024*1024;function Ue(e){return e.type.startsWith("image/")?true:/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico|avif|heic|heif|tiff|tif)$/i.test(e.name)}async function vt(e,r=200){return new Promise((t,a)=>{let i=new window.Image,o=URL.createObjectURL(e);i.onload=()=>{URL.revokeObjectURL(o);let d=Math.min(r/i.width,r/i.height,1),m=Math.round(i.width*d),u=Math.round(i.height*d),c=document.createElement("canvas");c.width=m,c.height=u;let g=c.getContext("2d");if(!g){a(new Error("Canvas context unavailable"));return}g.drawImage(i,0,0,m,u),c.toBlob(s=>{s?t(URL.createObjectURL(s)):a(new Error("Failed to create blob"));},"image/jpeg",.8);},i.onerror=()=>{URL.revokeObjectURL(o),a(new Error("Failed to load image"));},i.src=o;})}async function Me(e,r=200){return e.size>gt?vt(e,r):URL.createObjectURL(e)}function ze(e,r={}){let{enabled:t=true,maxBytes:a=10*1024*1024,maxDimension:i=200}=r,[o,d]=react.useState(null),[m,u]=react.useState(false),[c,g]=react.useState(null),s=Ue(e);return react.useEffect(()=>{if(!t||!s){d(null),u(false),g(null);return}if(e.size>a){d(null),u(false),g("File too large for preview");return}let h=true,V=null;return (async()=>{u(true),g(null);try{V=await Me(e,i),h?(d(V),u(!1)):URL.revokeObjectURL(V);}catch(I){h&&(g(I instanceof Error?I.message:"Failed to generate preview"),u(false),d(null));}})(),()=>{h=false,V&&URL.revokeObjectURL(V),d(I=>(I&&URL.revokeObjectURL(I),null));}},[e,t,a,i,s]),{preview:o,isLoading:m,error:c,isImage:s}}function Ge({file:e,size:r=64,maxBytes:t=10*1024*1024,renderPreview:a,className:i}){let{preview:o,isLoading:d,error:m,isImage:u}=ze(e,{enabled:true,maxBytes:t,maxDimension:r*2}),c={width:r,height:r,minWidth:r,minHeight:r};if(!u&&a)return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,children:a(e)});if(d)return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,"aria-busy":"true","aria-label":`Loading preview for ${e.name}`,children:jsxRuntime.jsx(lucideReact.Loader2,{className:"h-4 w-4 animate-spin text-[var(--menu-muted)]","aria-hidden":"true"})});if(u&&o&&!m)return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,children:jsxRuntime.jsx("img",{src:o,alt:e.name,className:"w-full h-full object-cover",loading:"lazy"})});let g=j(e),s=er(g),h=Math.max(16,Math.floor(r*.4));return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,"aria-label":m?`Preview unavailable for ${e.name}`:void 0,children:jsxRuntime.jsx(s,{className:"text-[var(--menu-muted)]",style:{width:h,height:h},"aria-hidden":"true"})})}function er(e){switch(e){case "image":return lucideReact.ImageIcon;case "video":return lucideReact.VideoIcon;case "audio":return lucideReact.AudioLines;default:return lucideReact.FileIcon}}var ke=classVarianceAuthority.cva(["flex","flex-col","gap-1","w-full"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),$e=classVarianceAuthority.cva(["rounded-full","bg-[var(--accent-background)]","overflow-hidden"],{variants:{size:{sm:"h-1.5",default:"h-2",lg:"h-3"}},defaultVariants:{size:"default"}}),je=classVarianceAuthority.cva(["h-full","rounded-full","transition-all","duration-300"],{variants:{status:{pending:["bg-gradient-to-r","from-[var(--menu-muted)]","via-[var(--accent-background)]","to-[var(--menu-muted)]","bg-[length:200%_100%]","animate-progress-shimmer"],uploading:"bg-[var(--primary)]",complete:"bg-[var(--success-background)]",error:"bg-[var(--destructive-background)]"}},defaultVariants:{status:"pending"}}),We=classVarianceAuthority.cva(["flex","items-center","justify-between","gap-2"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),Ze=classVarianceAuthority.cva(["flex","items-center","justify-between","gap-2","mt-1","text-[var(--destructive-background)]"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),Ye=classVarianceAuthority.cva(["underline","hover:no-underline","min-h-[44px]","min-w-[44px]","inline-flex","items-center","justify-center","-mr-3","-my-2","focus-visible:outline-none","focus-visible:ring-2","focus-visible:ring-[var(--ring)]","focus-visible:ring-offset-2","rounded"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}});function ar(e,r){switch(e){case "pending":return "Queued for upload\u2026";case "uploading":return `Uploading\u2026 ${r}%`;case "complete":return "Upload complete";case "error":return "Upload failed \u2014 try again"}}function le({file:e,progress:r,status:t,error:a,onRetry:i,size:o="default",className:d}){let m=t==="pending",u=`progress-error-${e.name.replace(/[^a-zA-Z0-9]/g,"-")}`,c=ar(t,r);return jsxRuntime.jsxs("div",{className:b(ke({size:o}),d),children:[jsxRuntime.jsx(reactAriaComponents.ProgressBar,{"aria-label":e.name,value:m?void 0:r,isIndeterminate:m,"aria-describedby":t==="error"&&a?u:void 0,children:({percentage:g,valueText:s})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("div",{className:We({size:o}),children:[jsxRuntime.jsx("span",{className:"truncate",title:e.name,children:$(e.name,30)}),jsxRuntime.jsx("span",{className:"text-[var(--menu-muted)] flex-shrink-0",children:t==="error"?c:s??c})]}),jsxRuntime.jsx("div",{className:$e({size:o}),children:jsxRuntime.jsx("div",{className:je({status:t}),style:{width:m?"100%":`${g??0}%`}})})]})}),t==="error"&&a&&jsxRuntime.jsxs("div",{id:u,className:Ze({size:o}),children:[jsxRuntime.jsx("span",{children:a}),i&&jsxRuntime.jsx(reactAriaComponents.Button,{onPress:i,className:Ye({size:o}),children:"Retry"})]}),jsxRuntime.jsxs("div",{"aria-live":"polite","aria-atomic":"true",className:"sr-only",children:[t==="complete"&&`${e.name} upload complete`,t==="error"&&`${e.name} upload failed${a?`: ${a}`:""}`]})]})}le.displayName="FileProgress";var bt=react.forwardRef(function({label:r,acceptedFileTypes:t,allowsMultiple:a=false,maxFileSize:i,maxFiles:o,description:d,errorMessage:m,successMessage:u,triggerText:c,isRequired:g,isDisabled:s,isInvalid:h,isValid:V,size:f="default",name:I,id:de,className:Y,value:v=[],onChange:N,validate:B,showPreviews:ue=false,previewSize:U=64,maxPreviewBytes:X=10*1024*1024,renderPreview:q,showProgress:ce=false,uploadProgress:M,uploadStatus:Xe,uploadErrors:qe,onRetry:R,"data-testid":Qe,"aria-label":xr,"aria-labelledby":br,"aria-describedby":Ke,...Et},ht){let It=react.useId(),Q=de??It,Je=`${Q}-label`,et=`${Q}-description`,tt=`${Q}-error`,[rt,fe]=react.useState(false),[Ft,pe]=react.useState(null),K=react.useRef(0),H=m??Ft,_t=h||!!H,z=[];Ke&&z.push(Ke),d&&z.push(et),H&&z.push(tt);let Tt=z.length>0?z.join(" "):void 0,at=react.useCallback((n,x=[])=>{let F=[],S=[];for(let E of n){if(t&&!Be(E,t)){S.push(`"${E.name}" is not a supported file type. Accepted: ${t}`);continue}if(i&&E.size>i){S.push(`"${E.name}" is too large (max ${se(i)}). Try compressing or resizing the file.`);continue}F.push(E);}return o&&a&&W(x,F).length>o?(S.push(`Maximum ${o} files allowed`),{valid:[],errors:S}):{valid:F,errors:S}},[t,i,o,a]),J=react.useCallback(n=>{if(!n||n.length===0)return;pe(null);let x=Array.from(n),F=a?v:[],{valid:S,errors:E}=at(x,F);if(E.length>0){pe(E[0]??"Invalid file");return}if(B&&S.length>0){let ee=B(a?W(F,S):S);if(ee){pe(ee);return}}let G;a?G=W(F,S):G=S.slice(0,1),N?.(G);},[a,v,at,B,N]),Vt=react.useCallback(n=>{J(n);},[J]),Nt=react.useCallback(n=>{let x=v.filter(F=>F!==n);N?.(x);},[v,N]),yt=react.useCallback(()=>{N?.([]);},[N]),Pt=react.useCallback(n=>{n.preventDefault(),n.stopPropagation(),!s&&(K.current++,fe(true));},[s]),Rt=react.useCallback(n=>{n.preventDefault(),n.stopPropagation();},[]),Ot=react.useCallback(n=>{n.preventDefault(),n.stopPropagation(),K.current--,K.current===0&&fe(false);},[]),At=react.useCallback(n=>{if(n.preventDefault(),n.stopPropagation(),K.current=0,fe(false),s)return;let x=n.dataTransfer?.files;J(x??null);},[s,J]),Lt=n=>{switch(j(n)){case "image":return lucideReact.ImageIcon;case "video":return lucideReact.VideoIcon;case "audio":return lucideReact.AudioLines;default:return lucideReact.FileIcon}},Dt=t?.join(",");return jsxRuntime.jsxs("div",{ref:ht,id:Q,className:b(Ne({size:f}),Y),"data-testid":Qe??"file-field",...Et,children:[jsxRuntime.jsx("label",{id:Je,className:Ce({size:f,isRequired:g}),children:r}),jsxRuntime.jsxs("div",{role:"group","data-testid":`${Qe??"file-field"}-dropzone`,className:b("drop-zone",ye({size:f,isDragOver:rt,isInvalid:_t,isDisabled:s})),onDragEnter:Pt,onDragOver:Rt,onDragLeave:Ot,onDrop:At,"aria-labelledby":Je,"aria-describedby":Tt,"aria-disabled":s||void 0,children:[jsxRuntime.jsx(reactAriaComponents.FileTrigger,{acceptedFileTypes:t,allowsMultiple:a,onSelect:Vt,children:jsxRuntime.jsxs(D,{variant:"outline",isDisabled:s,buttonVisualClassName:Pe({size:f}),children:[jsxRuntime.jsx(lucideReact.Upload,{className:"h-4 w-4","aria-hidden":"true"}),rt?"Drop files here":c??(a?"Choose files":"Choose file")]})}),I&&jsxRuntime.jsx("input",{type:"file",name:I,accept:Dt,multiple:a,disabled:s,className:"sr-only",tabIndex:-1,"aria-hidden":"true"})]}),d&&jsxRuntime.jsx("p",{id:et,className:we({size:f}),children:d}),v.length>0&&jsxRuntime.jsxs("div",{className:Re({size:f}),children:[v.length>=2&&jsxRuntime.jsxs("div",{className:mt({size:f}),children:[jsxRuntime.jsxs("span",{className:"text-[var(--menu-muted)]",children:[v.length," files selected"]}),jsxRuntime.jsx(D,{variant:"link",visualSize:"sm",onPress:yt,buttonVisualClassName:b("text-[var(--menu-muted)] hover:text-[var(--destructive-background)]","underline-offset-4 hover:underline"),"aria-label":"Clear all files",children:"Clear all"})]}),jsxRuntime.jsx("ul",{className:"space-y-2",children:v.map((n,x)=>{let F=Lt(n),S=f==="sm"?Math.min(U,40):f==="lg"?Math.min(U,80):Math.min(U,48),E=Xe?.[x],G=M?.[x]??0,ee=qe?.get(x),it=ce&&E!==void 0;return jsxRuntime.jsx("li",{className:it?"p-3":Oe({size:f}),children:it?jsxRuntime.jsx(le,{file:n,progress:G,status:E,error:ee,onRetry:R?()=>R(x):void 0,size:f}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[ue?jsxRuntime.jsx(Ge,{file:n,size:S,maxBytes:X,renderPreview:q,className:"flex-shrink-0"}):jsxRuntime.jsx(F,{className:"h-4 w-4 flex-shrink-0 text-[var(--menu-muted)]","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"truncate",title:n.name,children:$(n.name,30)}),jsxRuntime.jsx("span",{className:"text-[var(--menu-muted)] flex-shrink-0",children:se(n.size)})]}),jsxRuntime.jsx(D,{variant:"ghost",visualSize:"icon",onPress:()=>Nt(n),buttonVisualClassName:Ae({size:f}),"aria-label":`Remove ${n.name}`,isDisabled:s,children:jsxRuntime.jsx(lucideReact.X,{className:"h-4 w-4","aria-hidden":"true"})})]})},`${n.name}-${x}`)})})]}),H&&jsxRuntime.jsx("p",{id:tt,role:"alert",className:Le({size:f}),children:H}),!H&&V&&u&&jsxRuntime.jsx("p",{className:De({size:f}),children:u})]})});bt.displayName="FileField";var St=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var vr=St.extend({label:zod.z.string(),acceptedFileTypes:zod.z.array(zod.z.string()).optional(),allowsMultiple:zod.z.boolean().default(false),maxFileSize:zod.z.number().optional(),maxFiles:zod.z.number().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),successMessage:zod.z.string().optional(),triggerText:zod.z.string().optional(),isRequired:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),isInvalid:zod.z.boolean().optional(),isValid:zod.z.boolean().optional(),size:zod.z.enum(["sm","default","lg"]).default("default"),name:zod.z.string().optional(),showPreviews:zod.z.boolean().default(false),previewSize:zod.z.number().min(16).max(256).default(64),maxPreviewBytes:zod.z.number().default(10*1024*1024),showProgress:zod.z.boolean().default(false),uploadProgress:zod.z.array(zod.z.number().min(0).max(100)).optional(),uploadStatus:zod.z.array(zod.z.enum(["pending","uploading","complete","error"])).optional()}).refine(e=>!(e.successMessage&&e.errorMessage),{message:"Cannot provide both successMessage and errorMessage. Use one based on validation state.",path:["successMessage"]}).refine(e=>(typeof process<"u"&&process.env.NODE_ENV==="development"&&e.isValid&&e.isInvalid&&console.error("[FileField] Both isValid and isInvalid are true. isInvalid takes precedence."),true));exports.FileField=bt;exports.FileFieldPropsSchema=vr;exports.FilePreview=Ge;exports.FileProgress=le;exports.RESIZE_THRESHOLD=gt;exports.createResizedPreview=vt;exports.deduplicateFiles=W;exports.fileFieldContainerVariants=Ne;exports.fileFieldDescriptionVariants=we;exports.fileFieldDropZoneVariants=ye;exports.fileFieldErrorVariants=Le;exports.fileFieldItemVariants=Oe;exports.fileFieldLabelVariants=Ce;exports.fileFieldListVariants=Re;exports.fileFieldRemoveButtonVariants=Ae;exports.fileFieldSuccessVariants=De;exports.fileFieldTriggerVariants=Pe;exports.fileProgressBarVariants=je;exports.fileProgressErrorVariants=Ze;exports.fileProgressHeaderVariants=We;exports.fileProgressRetryVariants=Ye;exports.fileProgressTrackVariants=$e;exports.fileProgressVariants=ke;exports.formatAcceptedTypes=Zt;exports.formatFileSize=se;exports.generatePreview=Me;exports.getFileIcon=j;exports.isFileTypeAccepted=Be;exports.isImageFile=Ue;exports.truncateFileName=$;exports.useFilePreview=ze;//# sourceMappingURL=index.js.map
|
|
2
|
+
'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function b(...e){return tailwindMerge.twMerge(clsx.clsx(e))}var me=classVarianceAuthority.cva("inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",{variants:{fullWidth:{true:"w-full",false:""},inVerticalGroup:{true:"items-stretch",false:"items-center"}},defaultVariants:{fullWidth:false,inVerticalGroup:false}}),ge=classVarianceAuthority.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-normal ring-offset-background motion-safe:transition-transform motion-safe:duration-200 motion-safe:[transition-timing-function:cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer",{variants:{variant:{default:"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] hover:-translate-y-1",destructive:"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] hover:bg-[var(--destructive-background-hover,var(--destructive-background))] motion-safe:hover:btn-warn-shake",outline:"border border-[var(--input-border)] bg-[var(--content-background)] hover:bg-[var(--accent-background)]/50",secondary:"bg-[var(--secondary)] text-[var(--secondary-foreground)] hover:bg-[var(--secondary-hover,var(--secondary))]",ghost:"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]",link:"text-[var(--text-link)] underline underline-offset-4 hover:bg-[var(--accent)] hover:text-[var(--text-link-hover)]"},fullWidth:{true:"w-full",false:""},visualSize:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3 text-xs",lg:"h-11 rounded-md px-6 text-base",icon:"h-10 w-10",dot:"h-5 w-5 rounded-full p-0 min-h-0 min-w-0"},paywall:{true:"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent",false:""}},defaultVariants:{variant:"default",visualSize:"default",paywall:false}});var ve="data-[pressed]:scale-[0.97]";var te="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",re="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var dt=react.createContext(null);dt.displayName="ButtonGroupContext";function ut(){return react.useContext(dt)}var ct=react.createContext(null);ct.displayName="ButtonGroupItemContext";function ft(){return react.useContext(ct)}classVarianceAuthority.cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}});var pt=classVarianceAuthority.cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}});classVarianceAuthority.cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var D=react.memo(react.forwardRef(({className:e,buttonVisualClassName:r,variant:t,size:a,visualSize:i,fullWidth:o,loading:d=false,loadingText:m="Loading...",shortcut:u,children:c,isDisabled:g,paywall:s=false,paywallRedirect:h,paywallDescription:V,onPress:f,...I},de)=>{let Y=react.useId(),v=ut(),N=ft(),B=t??v?.variant??"default",ue=a??v?.size,U=g??v?.isDisabled??false,X=v?.orientation==="vertical",q=o||X,ce=N?pt({orientation:v?.orientation??"horizontal",position:N.position}):"",M=i??ue??"default";return process.env.NODE_ENV!=="production"&&(M==="dot"||M==="icon")&&!I["aria-label"]&&!c&&console.warn('[Button] visualSize="dot" or "icon" requires aria-label when no visible text is provided (WCAG 1.1.1)'),jsxRuntime.jsx(reactAriaComponents.Button,{ref:de,isDisabled:U||d||void 0,"aria-disabled":s?true:void 0,"aria-describedby":s?Y:void 0,onPress:R=>{if(s){h&&window.open(h,"_blank","noopener,noreferrer");return}f?.(R);},className:b(me({fullWidth:q,inVerticalGroup:X}),e),...I,children:R=>jsxRuntime.jsxs("span",{className:b(ge({variant:B,visualSize:M,paywall:s,fullWidth:q}),ce,r,ve,"",te,re),"data-pressed":R.isPressed||void 0,children:[d&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"motion-safe:animate-spin","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"sr-only","aria-live":"polite",children:m})]}),!d&&c,s&&jsxRuntime.jsx(lucideReact.Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),s&&jsxRuntime.jsxs("span",{id:Y,className:"sr-only",children:["Premium feature: ",V||"Upgrade required to access this feature"]}),R.isFocusVisible&&u&&jsxRuntime.jsx("kbd",{className:"ml-auto hidden text-xs opacity-60 lg:inline",children:u})]})})}));D.displayName="Button";var Ee=["focus-within:outline-none","focus-within:ring-2","focus-within:ring-[var(--ring)]","focus-within:ring-offset-2"],he=["focus-visible:outline-none","focus-visible:ring-2","focus-visible:ring-[var(--ring)]","focus-visible:ring-offset-2"];var Ie=["disabled:pointer-events-none","disabled:opacity-50"];var w={sm:"text-xs",default:"text-sm",lg:"text-base"},ie={sm:"text-sm",default:"text-base",lg:"text-lg"},ne=["min-h-[44px]","min-w-[44px]"];var Fe=["flex","items-center","gap-1.5","text-[var(--destructive-background)]"],_e=["flex","items-center","gap-1.5","text-[var(--success-background)]"],Te=["text-[var(--menu-muted)]"],Ve=["font-medium","text-[var(--content-foreground)]"];var oe=["transition-colors","duration-200"];function O(...e){return e.flatMap(r=>Array.isArray(r)?[...r]:[r])}var Ne=classVarianceAuthority.cva("flex flex-col gap-1.5 w-full",{variants:{size:ie},defaultVariants:{size:"default"}}),ye=classVarianceAuthority.cva(O("flex flex-col items-center justify-center rounded-md border-2 border-dashed","bg-[var(--content-background)] text-[var(--content-foreground)]",oe,Ee),{variants:{size:{sm:"min-h-[100px] p-4 gap-2",default:"min-h-[140px] p-6 gap-3",lg:"min-h-[180px] p-8 gap-4"},isDragOver:{true:"border-[var(--primary)] bg-[var(--primary)]/5",false:"border-[var(--input-border)] hover:border-[var(--primary)]/50"},isInvalid:{true:"border-[var(--destructive-background)] bg-[var(--destructive-background)]/5",false:""},isDisabled:{true:"opacity-50 cursor-not-allowed pointer-events-none",false:"cursor-pointer"}},compoundVariants:[{isInvalid:true,isDragOver:true,className:"border-[var(--destructive-background)] bg-[var(--destructive-background)]/5"}],defaultVariants:{size:"default",isDragOver:false,isInvalid:false,isDisabled:false}}),Pe=classVarianceAuthority.cva(O("inline-flex items-center justify-center gap-2 rounded-md font-medium",oe,ne,he,Ie),{variants:{size:{sm:"px-3 py-2 text-xs",default:"px-4 py-2 text-sm",lg:"px-6 py-3 text-base"},variant:{default:"bg-[var(--primary)] text-[var(--primary-foreground)] hover:bg-[var(--primary)]/90",outline:"border border-[var(--input-border)] bg-transparent hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]"}},defaultVariants:{size:"default",variant:"default"}}),Re=classVarianceAuthority.cva("flex flex-col gap-2 mt-3",{variants:{size:{sm:"gap-1.5",default:"gap-2",lg:"gap-3"}},defaultVariants:{size:"default"}}),mt=classVarianceAuthority.cva("flex items-center justify-between mb-1",{variants:{size:w},defaultVariants:{size:"default"}}),Oe=classVarianceAuthority.cva("flex items-center justify-between gap-3 bg-[var(--accent-background)] rounded-md border border-[var(--border)]",{variants:{size:{sm:"px-2 py-1.5 text-xs",default:"px-3 py-2 text-sm",lg:"px-4 py-3 text-base"}},defaultVariants:{size:"default"}}),Ae=classVarianceAuthority.cva(O("inline-flex items-center justify-center rounded-full",ne,"-mr-2 -my-1","text-[var(--menu-muted)] hover:text-[var(--destructive-background)] hover:bg-[var(--destructive-background)]/10","transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]"),{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),Le=classVarianceAuthority.cva(O(Fe,"font-medium"),{variants:{size:w},defaultVariants:{size:"default"}}),De=classVarianceAuthority.cva(O(_e,"font-medium"),{variants:{size:w},defaultVariants:{size:"default"}}),we=classVarianceAuthority.cva(Te,{variants:{size:w},defaultVariants:{size:"default"}}),Ce=classVarianceAuthority.cva(Ve,{variants:{size:ie,isRequired:{true:"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]",false:""}},defaultVariants:{size:"default",isRequired:false}});function se(e){if(e===0)return "0 B";let r=1024,t=["B","KB","MB","GB"],a=Math.floor(Math.log(e)/Math.log(r)),i=parseFloat((e/Math.pow(r,a)).toFixed(1));return `${i%1===0?i.toFixed(0):i.toFixed(1)} ${t[a]}`}function $(e,r=30){if(e.length<=r)return e;let t=e.lastIndexOf(".");if(t===-1)return `${e.slice(0,r-3)}...`;let a=e.slice(t),i=e.slice(0,t),o=r-a.length-3;return o<1?`...${a}`:`${i.slice(0,o)}...${a}`}function Be(e,r){return !r||r.length===0?true:r.some(t=>{if(t.endsWith("/*")){let a=t.slice(0,-2);return e.type.startsWith(`${a}/`)}return t.includes("/")?e.type===t:t.startsWith(".")?e.name.toLowerCase().endsWith(t.toLowerCase()):false})}function j(e){return e.type.startsWith("image/")?"image":e.type.startsWith("video/")?"video":e.type.startsWith("audio/")?"audio":"file"}function W(e,r){let t=[...e];for(let a of r){let i=t.findIndex(o=>o.name===a.name);i>=0?t[i]=a:t.push(a);}return t}function Zt(e){return !e||e.length===0?"any file":e.map(t=>t==="image/*"?"images":t==="video/*"?"videos":t==="audio/*"?"audio":t.startsWith(".")?t.slice(1).toUpperCase():t.includes("/")?(t.split("/")[1]??t).toUpperCase():t).join(", ")}var gt=2*1024*1024;function Ue(e){return e.type.startsWith("image/")?true:/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico|avif|heic|heif|tiff|tif)$/i.test(e.name)}async function vt(e,r=200){return new Promise((t,a)=>{let i=new window.Image,o=URL.createObjectURL(e);i.onload=()=>{URL.revokeObjectURL(o);let d=Math.min(r/i.width,r/i.height,1),m=Math.round(i.width*d),u=Math.round(i.height*d),c=document.createElement("canvas");c.width=m,c.height=u;let g=c.getContext("2d");if(!g){a(new Error("Canvas context unavailable"));return}g.drawImage(i,0,0,m,u),c.toBlob(s=>{s?t(URL.createObjectURL(s)):a(new Error("Failed to create blob"));},"image/jpeg",.8);},i.onerror=()=>{URL.revokeObjectURL(o),a(new Error("Failed to load image"));},i.src=o;})}async function Me(e,r=200){return e.size>gt?vt(e,r):URL.createObjectURL(e)}function ze(e,r={}){let{enabled:t=true,maxBytes:a=10*1024*1024,maxDimension:i=200}=r,[o,d]=react.useState(null),[m,u]=react.useState(false),[c,g]=react.useState(null),s=Ue(e);return react.useEffect(()=>{if(!t||!s){d(null),u(false),g(null);return}if(e.size>a){d(null),u(false),g("File too large for preview");return}let h=true,V=null;return (async()=>{u(true),g(null);try{V=await Me(e,i),h?(d(V),u(!1)):URL.revokeObjectURL(V);}catch(I){h&&(g(I instanceof Error?I.message:"Failed to generate preview"),u(false),d(null));}})(),()=>{h=false,V&&URL.revokeObjectURL(V),d(I=>(I&&URL.revokeObjectURL(I),null));}},[e,t,a,i,s]),{preview:o,isLoading:m,error:c,isImage:s}}function Ge({file:e,size:r=64,maxBytes:t=10*1024*1024,renderPreview:a,className:i}){let{preview:o,isLoading:d,error:m,isImage:u}=ze(e,{enabled:true,maxBytes:t,maxDimension:r*2}),c={width:r,height:r,minWidth:r,minHeight:r};if(!u&&a)return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,children:a(e)});if(d)return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,"aria-busy":"true","aria-label":`Loading preview for ${e.name}`,children:jsxRuntime.jsx(lucideReact.Loader2,{className:"h-4 w-4 animate-spin text-[var(--menu-muted)]","aria-hidden":"true"})});if(u&&o&&!m)return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,children:jsxRuntime.jsx("img",{src:o,alt:e.name,className:"w-full h-full object-cover",loading:"lazy"})});let g=j(e),s=er(g),h=Math.max(16,Math.floor(r*.4));return jsxRuntime.jsx("div",{className:b("flex items-center justify-center rounded-md overflow-hidden","bg-[var(--accent-background)]",i),style:c,"aria-label":m?`Preview unavailable for ${e.name}`:void 0,children:jsxRuntime.jsx(s,{className:"text-[var(--menu-muted)]",style:{width:h,height:h},"aria-hidden":"true"})})}function er(e){switch(e){case "image":return lucideReact.ImageIcon;case "video":return lucideReact.VideoIcon;case "audio":return lucideReact.AudioLines;default:return lucideReact.FileIcon}}var ke=classVarianceAuthority.cva(["flex","flex-col","gap-1","w-full"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),$e=classVarianceAuthority.cva(["rounded-full","bg-[var(--accent-background)]","overflow-hidden"],{variants:{size:{sm:"h-1.5",default:"h-2",lg:"h-3"}},defaultVariants:{size:"default"}}),je=classVarianceAuthority.cva(["h-full","rounded-full","transition-all","duration-300"],{variants:{status:{pending:["bg-gradient-to-r","from-[var(--menu-muted)]","via-[var(--accent-background)]","to-[var(--menu-muted)]","bg-[length:200%_100%]","animate-progress-shimmer"],uploading:"bg-[var(--primary)]",complete:"bg-[var(--success-background)]",error:"bg-[var(--destructive-background)]"}},defaultVariants:{status:"pending"}}),We=classVarianceAuthority.cva(["flex","items-center","justify-between","gap-2"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),Ze=classVarianceAuthority.cva(["flex","items-center","justify-between","gap-2","mt-1","text-[var(--destructive-background)]"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),Ye=classVarianceAuthority.cva(["underline","hover:no-underline","min-h-[44px]","min-w-[44px]","inline-flex","items-center","justify-center","-mr-3","-my-2","focus-visible:outline-none","focus-visible:ring-2","focus-visible:ring-[var(--ring)]","focus-visible:ring-offset-2","rounded"],{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}});function ar(e,r){switch(e){case "pending":return "Queued for upload\u2026";case "uploading":return `Uploading\u2026 ${r}%`;case "complete":return "Upload complete";case "error":return "Upload failed \u2014 try again"}}function le({file:e,progress:r,status:t,error:a,onRetry:i,size:o="default",className:d}){let m=t==="pending",u=`progress-error-${e.name.replace(/[^a-zA-Z0-9]/g,"-")}`,c=ar(t,r);return jsxRuntime.jsxs("div",{className:b(ke({size:o}),d),children:[jsxRuntime.jsx(reactAriaComponents.ProgressBar,{"aria-label":e.name,value:m?void 0:r,isIndeterminate:m,"aria-describedby":t==="error"&&a?u:void 0,children:({percentage:g,valueText:s})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("div",{className:We({size:o}),children:[jsxRuntime.jsx("span",{className:"truncate",title:e.name,children:$(e.name,30)}),jsxRuntime.jsx("span",{className:"text-[var(--menu-muted)] flex-shrink-0",children:t==="error"?c:s??c})]}),jsxRuntime.jsx("div",{className:$e({size:o}),children:jsxRuntime.jsx("div",{className:je({status:t}),style:{width:m?"100%":`${g??0}%`}})})]})}),t==="error"&&a&&jsxRuntime.jsxs("div",{id:u,className:Ze({size:o}),children:[jsxRuntime.jsx("span",{children:a}),i&&jsxRuntime.jsx(reactAriaComponents.Button,{onPress:i,className:Ye({size:o}),children:"Retry"})]}),jsxRuntime.jsxs("div",{"aria-live":"polite","aria-atomic":"true",className:"sr-only",children:[t==="complete"&&`${e.name} upload complete`,t==="error"&&`${e.name} upload failed${a?`: ${a}`:""}`]})]})}le.displayName="FileProgress";var bt=react.forwardRef(function({label:r,acceptedFileTypes:t,allowsMultiple:a=false,maxFileSize:i,maxFiles:o,description:d,errorMessage:m,successMessage:u,triggerText:c,isRequired:g,isDisabled:s,isInvalid:h,isValid:V,size:f="default",name:I,id:de,className:Y,value:v=[],onChange:N,validate:B,showPreviews:ue=false,previewSize:U=64,maxPreviewBytes:X=10*1024*1024,renderPreview:q,showProgress:ce=false,uploadProgress:M,uploadStatus:Xe,uploadErrors:qe,onRetry:R,"data-testid":Qe,"aria-label":xr,"aria-labelledby":br,"aria-describedby":Ke,...Et},ht){let It=react.useId(),Q=de??It,Je=`${Q}-label`,et=`${Q}-description`,tt=`${Q}-error`,[rt,fe]=react.useState(false),[Ft,pe]=react.useState(null),K=react.useRef(0),H=m??Ft,_t=h||!!H,z=[];Ke&&z.push(Ke),d&&z.push(et),H&&z.push(tt);let Tt=z.length>0?z.join(" "):void 0,at=react.useCallback((n,x=[])=>{let F=[],S=[];for(let E of n){if(t&&!Be(E,t)){S.push(`"${E.name}" is not a supported file type. Accepted: ${t}`);continue}if(i&&E.size>i){S.push(`"${E.name}" is too large (max ${se(i)}). Try compressing or resizing the file.`);continue}F.push(E);}return o&&a&&W(x,F).length>o?(S.push(`Maximum ${o} files allowed`),{valid:[],errors:S}):{valid:F,errors:S}},[t,i,o,a]),J=react.useCallback(n=>{if(!n||n.length===0)return;pe(null);let x=Array.from(n),F=a?v:[],{valid:S,errors:E}=at(x,F);if(E.length>0){pe(E[0]??"Invalid file");return}if(B&&S.length>0){let ee=B(a?W(F,S):S);if(ee){pe(ee);return}}let G;a?G=W(F,S):G=S.slice(0,1),N?.(G);},[a,v,at,B,N]),Vt=react.useCallback(n=>{J(n);},[J]),Nt=react.useCallback(n=>{let x=v.filter(F=>F!==n);N?.(x);},[v,N]),yt=react.useCallback(()=>{N?.([]);},[N]),Pt=react.useCallback(n=>{n.preventDefault(),n.stopPropagation(),!s&&(K.current++,fe(true));},[s]),Rt=react.useCallback(n=>{n.preventDefault(),n.stopPropagation();},[]),Ot=react.useCallback(n=>{n.preventDefault(),n.stopPropagation(),K.current--,K.current===0&&fe(false);},[]),At=react.useCallback(n=>{if(n.preventDefault(),n.stopPropagation(),K.current=0,fe(false),s)return;let x=n.dataTransfer?.files;J(x??null);},[s,J]),Lt=n=>{switch(j(n)){case "image":return lucideReact.ImageIcon;case "video":return lucideReact.VideoIcon;case "audio":return lucideReact.AudioLines;default:return lucideReact.FileIcon}},Dt=t?.join(",");return jsxRuntime.jsxs("div",{ref:ht,id:Q,className:b(Ne({size:f}),Y),"data-testid":Qe??"file-field",...Et,children:[jsxRuntime.jsx("label",{id:Je,className:Ce({size:f,isRequired:g}),children:r}),jsxRuntime.jsxs("div",{role:"group","data-testid":`${Qe??"file-field"}-dropzone`,className:b("drop-zone",ye({size:f,isDragOver:rt,isInvalid:_t,isDisabled:s})),onDragEnter:Pt,onDragOver:Rt,onDragLeave:Ot,onDrop:At,"aria-labelledby":Je,"aria-describedby":Tt,"aria-disabled":s||void 0,children:[jsxRuntime.jsx(reactAriaComponents.FileTrigger,{acceptedFileTypes:t,allowsMultiple:a,onSelect:Vt,children:jsxRuntime.jsxs(D,{variant:"outline",isDisabled:s,buttonVisualClassName:Pe({size:f}),children:[jsxRuntime.jsx(lucideReact.Upload,{className:"h-4 w-4","aria-hidden":"true"}),rt?"Drop files here":c??(a?"Choose files":"Choose file")]})}),I&&jsxRuntime.jsx("input",{type:"file",name:I,accept:Dt,multiple:a,disabled:s,className:"sr-only",tabIndex:-1,"aria-hidden":"true"})]}),d&&jsxRuntime.jsx("p",{id:et,className:we({size:f}),children:d}),v.length>0&&jsxRuntime.jsxs("div",{className:Re({size:f}),children:[v.length>=2&&jsxRuntime.jsxs("div",{className:mt({size:f}),children:[jsxRuntime.jsxs("span",{className:"text-[var(--menu-muted)]",children:[v.length," files selected"]}),jsxRuntime.jsx(D,{variant:"link",visualSize:"sm",onPress:yt,buttonVisualClassName:b("text-[var(--menu-muted)] hover:text-[var(--destructive-background)]","underline-offset-4 hover:underline"),"aria-label":"Clear all files",children:"Clear all"})]}),jsxRuntime.jsx("ul",{className:"space-y-2",children:v.map((n,x)=>{let F=Lt(n),S=f==="sm"?Math.min(U,40):f==="lg"?Math.min(U,80):Math.min(U,48),E=Xe?.[x],G=M?.[x]??0,ee=qe?.get(x),it=ce&&E!==void 0;return jsxRuntime.jsx("li",{className:it?"p-3":Oe({size:f}),children:it?jsxRuntime.jsx(le,{file:n,progress:G,status:E,error:ee,onRetry:R?()=>R(x):void 0,size:f}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[ue?jsxRuntime.jsx(Ge,{file:n,size:S,maxBytes:X,renderPreview:q,className:"flex-shrink-0"}):jsxRuntime.jsx(F,{className:"h-4 w-4 flex-shrink-0 text-[var(--menu-muted)]","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"truncate",title:n.name,children:$(n.name,30)}),jsxRuntime.jsx("span",{className:"text-[var(--menu-muted)] flex-shrink-0",children:se(n.size)})]}),jsxRuntime.jsx(D,{variant:"ghost",visualSize:"icon",onPress:()=>Nt(n),buttonVisualClassName:Ae({size:f}),"aria-label":`Remove ${n.name}`,isDisabled:s,children:jsxRuntime.jsx(lucideReact.X,{className:"h-4 w-4","aria-hidden":"true"})})]})},`${n.name}-${x}`)})})]}),H&&jsxRuntime.jsx("p",{id:tt,role:"alert",className:Le({size:f}),children:H}),!H&&V&&u&&jsxRuntime.jsx("p",{className:De({size:f}),children:u})]})});bt.displayName="FileField";var St=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var vr=St.extend({label:zod.z.string(),acceptedFileTypes:zod.z.array(zod.z.string()).optional(),allowsMultiple:zod.z.boolean().default(false),maxFileSize:zod.z.number().optional(),maxFiles:zod.z.number().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),successMessage:zod.z.string().optional(),triggerText:zod.z.string().optional(),isRequired:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),isInvalid:zod.z.boolean().optional(),isValid:zod.z.boolean().optional(),size:zod.z.enum(["sm","default","lg"]).default("default"),name:zod.z.string().optional(),showPreviews:zod.z.boolean().default(false),previewSize:zod.z.number().min(16).max(256).default(64),maxPreviewBytes:zod.z.number().default(10*1024*1024),showProgress:zod.z.boolean().default(false),uploadProgress:zod.z.array(zod.z.number().min(0).max(100)).optional(),uploadStatus:zod.z.array(zod.z.enum(["pending","uploading","complete","error"])).optional()}).refine(e=>!(e.successMessage&&e.errorMessage),{message:"Cannot provide both successMessage and errorMessage. Use one based on validation state.",path:["successMessage"]}).refine(e=>(typeof process<"u"&&process.env.NODE_ENV==="development"&&e.isValid&&e.isInvalid&&console.error("[FileField] Both isValid and isInvalid are true. isInvalid takes precedence."),true));exports.FileField=bt;exports.FileFieldPropsSchema=vr;exports.FilePreview=Ge;exports.FileProgress=le;exports.RESIZE_THRESHOLD=gt;exports.createResizedPreview=vt;exports.deduplicateFiles=W;exports.fileFieldContainerVariants=Ne;exports.fileFieldDescriptionVariants=we;exports.fileFieldDropZoneVariants=ye;exports.fileFieldErrorVariants=Le;exports.fileFieldItemVariants=Oe;exports.fileFieldLabelVariants=Ce;exports.fileFieldListVariants=Re;exports.fileFieldRemoveButtonVariants=Ae;exports.fileFieldSuccessVariants=De;exports.fileFieldTriggerVariants=Pe;exports.fileProgressBarVariants=je;exports.fileProgressErrorVariants=Ze;exports.fileProgressHeaderVariants=We;exports.fileProgressRetryVariants=Ye;exports.fileProgressTrackVariants=$e;exports.fileProgressVariants=ke;exports.formatAcceptedTypes=Zt;exports.formatFileSize=se;exports.generatePreview=Me;exports.getFileIcon=j;exports.isFileTypeAccepted=Be;exports.isImageFile=Ue;exports.truncateFileName=$;exports.useFilePreview=ze;//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|