@inkra/react 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +213 -2
- package/THIRD_PARTY_NOTICES.md +39 -0
- package/Yozai-OFL.txt +94 -0
- package/dist/Button.d.ts +36 -0
- package/dist/Button.js +89 -0
- package/dist/PencilIcon.d.ts +22 -0
- package/dist/PencilIcon.js +212 -0
- package/dist/PencilLine.d.ts +10 -0
- package/dist/PencilLine.js +85 -0
- package/dist/PencilSurface.d.ts +19 -0
- package/dist/PencilSurface.js +19 -0
- package/dist/PencilText.d.ts +16 -0
- package/dist/PencilText.js +205 -0
- package/dist/accordion/Accordion.d.ts +27 -0
- package/dist/accordion/Accordion.js +40 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +1 -0
- package/dist/assets/ui-hand-yozai.woff2 +0 -0
- package/dist/breadcrumb/index.d.ts +16 -0
- package/dist/breadcrumb/index.js +25 -0
- package/dist/calendar/index.d.ts +21 -0
- package/dist/calendar/index.js +41 -0
- package/dist/content/index.d.ts +106 -0
- package/dist/content/index.js +80 -0
- package/dist/day-agenda/index.d.ts +43 -0
- package/dist/day-agenda/index.js +47 -0
- package/dist/day-agenda/layout.d.ts +20 -0
- package/dist/day-agenda/layout.js +60 -0
- package/dist/display/index.d.ts +32 -0
- package/dist/display/index.js +59 -0
- package/dist/dropdown-menu/index.d.ts +34 -0
- package/dist/dropdown-menu/index.js +40 -0
- package/dist/form/EditablePencilText.d.ts +13 -0
- package/dist/form/EditablePencilText.js +312 -0
- package/dist/form/Field.d.ts +13 -0
- package/dist/form/Field.js +26 -0
- package/dist/form/Input.d.ts +27 -0
- package/dist/form/Input.js +97 -0
- package/dist/form/InputAction.d.ts +7 -0
- package/dist/form/InputAction.js +24 -0
- package/dist/form/Textarea.d.ts +5 -0
- package/dist/form/Textarea.js +23 -0
- package/dist/form/context.d.ts +12 -0
- package/dist/form/context.js +10 -0
- package/dist/form/controlProps.d.ts +23 -0
- package/dist/form/controlProps.js +20 -0
- package/dist/form/index.d.ts +7 -0
- package/dist/form/index.js +3 -0
- package/dist/form/types.d.ts +6 -0
- package/dist/form/types.js +1 -0
- package/dist/images/layers-2x.png +0 -0
- package/dist/images/layers.png +0 -0
- package/dist/images/marker-icon.png +0 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +22 -0
- package/dist/input-number/index.d.ts +16 -0
- package/dist/input-number/index.js +77 -0
- package/dist/internal/InputActionContext.d.ts +1 -0
- package/dist/internal/InputActionContext.js +3 -0
- package/dist/internal/cache.d.ts +14 -0
- package/dist/internal/cache.js +54 -0
- package/dist/internal/line.d.ts +4 -0
- package/dist/internal/line.js +21 -0
- package/dist/internal/paper.d.ts +1 -0
- package/dist/internal/paper.js +65 -0
- package/dist/internal/random.d.ts +3 -0
- package/dist/internal/random.js +30 -0
- package/dist/internal/recovery.d.ts +1 -0
- package/dist/internal/recovery.js +52 -0
- package/dist/internal/stroke.d.ts +24 -0
- package/dist/internal/stroke.js +144 -0
- package/dist/internal/surfaceRenderer.d.ts +33 -0
- package/dist/internal/surfaceRenderer.js +175 -0
- package/dist/internal/textQueue.d.ts +1 -0
- package/dist/internal/textQueue.js +37 -0
- package/dist/internal/textRenderer.d.ts +27 -0
- package/dist/internal/textRenderer.js +213 -0
- package/dist/internal/travelIcons.d.ts +24 -0
- package/dist/internal/travelIcons.js +14 -0
- package/dist/internal/useBrowserLayoutEffect.d.ts +2 -0
- package/dist/internal/useBrowserLayoutEffect.js +3 -0
- package/dist/internal/usePencilSurface.d.ts +3 -0
- package/dist/internal/usePencilSurface.js +108 -0
- package/dist/internal/useSelectionDrawing.d.ts +2 -0
- package/dist/internal/useSelectionDrawing.js +86 -0
- package/dist/internal/wash.d.ts +16 -0
- package/dist/internal/wash.js +149 -0
- package/dist/journey-map/MapScale.d.ts +4 -0
- package/dist/journey-map/MapScale.js +52 -0
- package/dist/journey-map/index.d.ts +39 -0
- package/dist/journey-map/index.js +195 -0
- package/dist/journey-map/terrain.d.ts +8 -0
- package/dist/journey-map/terrain.js +127 -0
- package/dist/overlay/Overlay.d.ts +65 -0
- package/dist/overlay/Overlay.js +77 -0
- package/dist/overlay/Popover.d.ts +43 -0
- package/dist/overlay/Popover.js +45 -0
- package/dist/overlay/index.d.ts +4 -0
- package/dist/overlay/index.js +2 -0
- package/dist/overlay/themeBridge.d.ts +8 -0
- package/dist/overlay/themeBridge.js +98 -0
- package/dist/pencil.d.ts +10 -0
- package/dist/pencil.js +39 -0
- package/dist/select/MultipleSelect.d.ts +44 -0
- package/dist/select/MultipleSelect.js +124 -0
- package/dist/select/SearchableSelect.d.ts +45 -0
- package/dist/select/SearchableSelect.js +50 -0
- package/dist/select/Select.d.ts +109 -0
- package/dist/select/Select.js +205 -0
- package/dist/select/index.d.ts +4 -0
- package/dist/select/index.js +2 -0
- package/dist/selection/Checkbox.d.ts +9 -0
- package/dist/selection/Checkbox.js +37 -0
- package/dist/selection/RadioGroup.d.ts +23 -0
- package/dist/selection/RadioGroup.js +82 -0
- package/dist/selection/Switch.d.ts +8 -0
- package/dist/selection/Switch.js +36 -0
- package/dist/selection/index.d.ts +6 -0
- package/dist/selection/index.js +3 -0
- package/dist/selection/useNativeChecked.d.ts +13 -0
- package/dist/selection/useNativeChecked.js +27 -0
- package/dist/slider/index.d.ts +11 -0
- package/dist/slider/index.js +45 -0
- package/dist/styles.css +3663 -0
- package/dist/tabs/index.d.ts +22 -0
- package/dist/tabs/index.js +42 -0
- package/dist/tokens.css +355 -0
- package/dist/tooltip/Tooltip.d.ts +24 -0
- package/dist/tooltip/Tooltip.js +32 -0
- package/dist/tooltip/index.d.ts +2 -0
- package/dist/tooltip/index.js +1 -0
- package/package.json +100 -4
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
import { type ButtonLinkProps } from '../Button.js';
|
|
3
|
+
export type BreadcrumbProps = ComponentPropsWithoutRef<'nav'>;
|
|
4
|
+
export type BreadcrumbListProps = ComponentPropsWithoutRef<'ol'>;
|
|
5
|
+
export type BreadcrumbItemProps = ComponentPropsWithoutRef<'li'>;
|
|
6
|
+
export type BreadcrumbLinkProps = ButtonLinkProps;
|
|
7
|
+
export type BreadcrumbPageProps = ComponentPropsWithoutRef<'span'>;
|
|
8
|
+
export type BreadcrumbSeparatorProps = ComponentPropsWithoutRef<'li'>;
|
|
9
|
+
export declare const Breadcrumb: {
|
|
10
|
+
Root: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & import("react").RefAttributes<HTMLElement>>;
|
|
11
|
+
List: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").OlHTMLAttributes<HTMLOListElement>, HTMLOListElement>, "ref"> & import("react").RefAttributes<HTMLOListElement>>;
|
|
12
|
+
Item: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & import("react").RefAttributes<HTMLLIElement>>;
|
|
13
|
+
Link: import("react").ForwardRefExoticComponent<ButtonLinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
|
|
14
|
+
Page: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
|
|
15
|
+
Separator: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & import("react").RefAttributes<HTMLLIElement>>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { ButtonLink } from '../Button.js';
|
|
4
|
+
import { PencilText } from '../PencilText.js';
|
|
5
|
+
const classes = (...values) => values.filter(Boolean).join(' ');
|
|
6
|
+
const copy = (children) => typeof children === 'string' ? _jsx(PencilText, { children: children }) : children;
|
|
7
|
+
const Root = forwardRef(function BreadcrumbRoot({ className, 'aria-label': label = 'Breadcrumb', ...props }, ref) {
|
|
8
|
+
return _jsx("nav", { ...props, ref: ref, "aria-label": label, className: classes('inkra-breadcrumb', className) });
|
|
9
|
+
});
|
|
10
|
+
const List = forwardRef(function BreadcrumbList({ className, ...props }, ref) {
|
|
11
|
+
return _jsx("ol", { ...props, ref: ref, className: classes('inkra-breadcrumb__list', className) });
|
|
12
|
+
});
|
|
13
|
+
const Item = forwardRef(function BreadcrumbItem({ className, ...props }, ref) {
|
|
14
|
+
return _jsx("li", { ...props, ref: ref, className: classes('inkra-breadcrumb__item', className) });
|
|
15
|
+
});
|
|
16
|
+
const Link = forwardRef(function BreadcrumbLink({ className, variant = 'ghost', ...props }, ref) {
|
|
17
|
+
return _jsx(ButtonLink, { ...props, ref: ref, variant: variant, className: classes('inkra-breadcrumb__link', className) });
|
|
18
|
+
});
|
|
19
|
+
const Page = forwardRef(function BreadcrumbPage({ className, children, ...props }, ref) {
|
|
20
|
+
return _jsx("span", { ...props, ref: ref, "aria-current": "page", className: classes('inkra-breadcrumb__page', className), children: copy(children) });
|
|
21
|
+
});
|
|
22
|
+
const Separator = forwardRef(function BreadcrumbSeparator({ className, children = '/', ...props }, ref) {
|
|
23
|
+
return _jsx("li", { ...props, ref: ref, role: "presentation", "aria-hidden": "true", className: classes('inkra-breadcrumb__separator', className), children: copy(children) });
|
|
24
|
+
});
|
|
25
|
+
export const Breadcrumb = { Root, List, Item, Link, Page, Separator };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type DayPickerProps } from 'react-day-picker';
|
|
3
|
+
export interface CalendarEvent {
|
|
4
|
+
date: Date;
|
|
5
|
+
label: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
color?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
}
|
|
10
|
+
export type CalendarProps = DayPickerProps & {
|
|
11
|
+
events?: readonly CalendarEvent[];
|
|
12
|
+
eventIndicator?: 'count' | 'dot' | 'none';
|
|
13
|
+
appearance?: 'itinerary' | 'picker';
|
|
14
|
+
onEventSelect?: (event: CalendarEvent) => void;
|
|
15
|
+
renderDayAccessory?: (date: Date) => ReactNode;
|
|
16
|
+
displayRange?: {
|
|
17
|
+
from: Date;
|
|
18
|
+
to: Date;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare function Calendar({ events, eventIndicator, appearance, onEventSelect, renderDayAccessory, displayRange, className, components, showOutsideDays, ...props }: CalendarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
import { CaptionLabel, Day, DayButton, DayPicker, Weekday } from 'react-day-picker';
|
|
4
|
+
import { Button } from '../Button.js';
|
|
5
|
+
import { PencilIcon } from '../PencilIcon.js';
|
|
6
|
+
import { PencilSurface } from '../PencilSurface.js';
|
|
7
|
+
import { PencilText } from '../PencilText.js';
|
|
8
|
+
const EventContext = createContext({ events: [], indicator: 'count', appearance: 'itinerary' });
|
|
9
|
+
const matches = (event, date) => event.date.getFullYear() === date.getFullYear()
|
|
10
|
+
&& event.date.getMonth() === date.getMonth() && event.date.getDate() === date.getDate();
|
|
11
|
+
function CalendarCaption({ children, ...props }) {
|
|
12
|
+
return _jsx(CaptionLabel, { ...props, children: typeof children === 'string' ? _jsx(PencilText, { children: children }) : children });
|
|
13
|
+
}
|
|
14
|
+
function CalendarWeekday({ children, ...props }) {
|
|
15
|
+
return _jsx(Weekday, { ...props, children: typeof children === 'string' ? _jsx(PencilText, { children: children }) : children });
|
|
16
|
+
}
|
|
17
|
+
function CalendarMonthButton({ disabled, ...props }) {
|
|
18
|
+
return _jsx(Button, { ...props, size: "icon", variant: "ghost", disabled: disabled || props['aria-disabled'] === true || props['aria-disabled'] === 'true' });
|
|
19
|
+
}
|
|
20
|
+
// Lucide chevrons retain their geometry and use the shared pencil renderer.
|
|
21
|
+
const chevrons = { left: 'm15 18-6-6 6-6', right: 'm9 18 6-6-6-6', up: 'm18 15-6-6-6 6', down: 'm6 9 6 6 6-6' };
|
|
22
|
+
function CalendarChevron({ className, orientation = 'left', size = 28 }) {
|
|
23
|
+
return _jsx(PencilIcon, { className: className, paths: [{ d: chevrons[orientation] }], sourceSize: 24, size: size });
|
|
24
|
+
}
|
|
25
|
+
// The trip calendar uses a full-cell date target with sibling event buttons.
|
|
26
|
+
function CalendarCell({ children, day, modifiers, ...props }) {
|
|
27
|
+
const { events, appearance, onEventSelect, renderDayAccessory } = useContext(EventContext);
|
|
28
|
+
if (appearance === 'picker')
|
|
29
|
+
return _jsx(Day, { ...props, day: day, modifiers: modifiers, children: children });
|
|
30
|
+
const entries = events.filter(event => matches(event, day.date));
|
|
31
|
+
return _jsx(Day, { ...props, day: day, modifiers: modifiers, children: _jsxs("div", { className: "inkra-calendar__day-card", children: [_jsx(PencilSurface, { variant: modifiers.selected ? 'action' : 'quiet', radius: 8, className: "inkra-calendar__day-paper", "aria-hidden": "true", seed: `day-${day.date.toISOString()}` }), children, renderDayAccessory && _jsx("div", { className: "inkra-calendar__accessory", children: renderDayAccessory(day.date) }), _jsx("div", { className: "inkra-calendar__events", children: entries.map((event, index) => _jsx(PencilSurface, { as: "button", variant: "quiet", radius: 3, className: "inkra-calendar__event-card", disabled: modifiers.disabled || !onEventSelect, style: event.color ? { '--inkra-accent-soft': event.color } : undefined, "aria-label": `${event.label}${event.description ? `, ${event.description}` : ''}`, title: event.description ?? event.label, onClick: click => { click.stopPropagation(); onEventSelect?.(event); }, children: _jsx(PencilText, { ellipsis: true, children: event.label }) }, event.id ?? index)) })] }) });
|
|
32
|
+
}
|
|
33
|
+
function CalendarDay({ children, modifiers, day, ...props }) {
|
|
34
|
+
const { events: allEvents, indicator, appearance } = useContext(EventContext);
|
|
35
|
+
const events = allEvents.filter(event => matches(event, day.date));
|
|
36
|
+
return _jsxs(DayButton, { ...props, day: day, modifiers: modifiers, "aria-label": [props['aria-label'], ...events.map(event => event.label)].filter(Boolean).join(', '), children: [modifiers.selected && appearance === 'picker' && _jsx(PencilSurface, { variant: "selection", className: "inkra-calendar__selection", "aria-hidden": "true" }), _jsx(PencilText, { children: String(children) }), appearance === 'picker' && events.length > 0 && indicator !== 'none' && _jsx("span", { className: "inkra-calendar__event", "data-indicator": indicator, "aria-hidden": "true", children: indicator === 'count' ? events.length : '\u2022' })] });
|
|
37
|
+
}
|
|
38
|
+
export function Calendar({ events = [], eventIndicator = 'count', appearance = 'itinerary', onEventSelect, renderDayAccessory, displayRange, className, components, showOutsideDays = true, ...props }) {
|
|
39
|
+
const hidden = displayRange ? [...(Array.isArray(props.hidden) ? props.hidden : props.hidden ? [props.hidden] : []), { before: displayRange.from }, { after: displayRange.to }] : props.hidden;
|
|
40
|
+
return _jsx(EventContext.Provider, { value: { events, indicator: eventIndicator, appearance, onEventSelect, renderDayAccessory }, children: _jsx("div", { className: "inkra-calendar-scroll", "data-appearance": appearance, children: _jsx(DayPicker, { ...props, hidden: hidden, "data-appearance": appearance, "data-week-numbers": props.showWeekNumber || undefined, showOutsideDays: showOutsideDays, className: ['inkra-calendar', className].filter(Boolean).join(' '), components: { CaptionLabel: CalendarCaption, Weekday: CalendarWeekday, Chevron: CalendarChevron, PreviousMonthButton: CalendarMonthButton, NextMonthButton: CalendarMonthButton, Day: CalendarCell, DayButton: CalendarDay, ...components } }) }) });
|
|
41
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
2
|
+
import { type HTMLAttributes, type ComponentPropsWithoutRef, type ReactNode } from 'react';
|
|
3
|
+
export type ContentSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
export type CardPadding = 'inherit' | 'none' | ContentSize;
|
|
5
|
+
export interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
variant?: 'paper' | 'quiet' | 'outline';
|
|
7
|
+
radius?: number;
|
|
8
|
+
seed?: string | number;
|
|
9
|
+
size?: ContentSize;
|
|
10
|
+
divided?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
|
|
13
|
+
action?: ReactNode;
|
|
14
|
+
divided?: boolean;
|
|
15
|
+
padding?: CardPadding;
|
|
16
|
+
align?: 'start' | 'center' | 'end';
|
|
17
|
+
}
|
|
18
|
+
export interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {
|
|
19
|
+
as?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
20
|
+
}
|
|
21
|
+
export interface CardContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
22
|
+
padding?: CardPadding;
|
|
23
|
+
}
|
|
24
|
+
export interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
|
|
25
|
+
divided?: boolean;
|
|
26
|
+
justify?: 'start' | 'center' | 'end' | 'between';
|
|
27
|
+
padding?: CardPadding;
|
|
28
|
+
orientation?: 'horizontal' | 'vertical';
|
|
29
|
+
}
|
|
30
|
+
export declare const Card: {
|
|
31
|
+
Root: import("react").ForwardRefExoticComponent<CardProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
32
|
+
Header: import("react").ForwardRefExoticComponent<CardHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
33
|
+
Title: import("react").ForwardRefExoticComponent<CardTitleProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
34
|
+
Description: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
35
|
+
Content: import("react").ForwardRefExoticComponent<CardContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
36
|
+
Footer: import("react").ForwardRefExoticComponent<CardFooterProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
37
|
+
};
|
|
38
|
+
export type AlertVariant = 'info' | 'success' | 'warning' | 'danger';
|
|
39
|
+
export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
|
|
40
|
+
variant?: AlertVariant;
|
|
41
|
+
icon?: ReactNode;
|
|
42
|
+
seed?: string | number;
|
|
43
|
+
size?: ContentSize;
|
|
44
|
+
appearance?: 'soft' | 'outline';
|
|
45
|
+
actions?: ReactNode;
|
|
46
|
+
}
|
|
47
|
+
export declare const Alert: {
|
|
48
|
+
Root: import("react").ForwardRefExoticComponent<AlertProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
49
|
+
Title: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
50
|
+
Description: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
51
|
+
};
|
|
52
|
+
export interface AvatarProps extends Omit<AvatarPrimitive.AvatarProps, 'asChild'> {
|
|
53
|
+
size?: 'sm' | 'md' | 'lg';
|
|
54
|
+
radius?: number;
|
|
55
|
+
bordered?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export type AvatarImageProps = Omit<AvatarPrimitive.AvatarImageProps, 'asChild' | 'alt'> & {
|
|
58
|
+
alt: string;
|
|
59
|
+
fit?: 'cover' | 'contain';
|
|
60
|
+
};
|
|
61
|
+
export type AvatarFallbackProps = Omit<AvatarPrimitive.AvatarFallbackProps, 'asChild'>;
|
|
62
|
+
export declare const Avatar: {
|
|
63
|
+
Root: import("react").ForwardRefExoticComponent<AvatarProps & import("react").RefAttributes<HTMLSpanElement>>;
|
|
64
|
+
Image: import("react").ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps, "asChild" | "alt"> & {
|
|
65
|
+
alt: string;
|
|
66
|
+
fit?: "cover" | "contain";
|
|
67
|
+
} & import("react").RefAttributes<HTMLImageElement>>;
|
|
68
|
+
Fallback: import("react").ForwardRefExoticComponent<AvatarFallbackProps & import("react").RefAttributes<HTMLSpanElement>>;
|
|
69
|
+
};
|
|
70
|
+
export interface TableProps extends ComponentPropsWithoutRef<'table'> {
|
|
71
|
+
density?: 'compact' | 'comfortable';
|
|
72
|
+
striped?: boolean;
|
|
73
|
+
hoverable?: boolean;
|
|
74
|
+
stickyHeader?: boolean;
|
|
75
|
+
captionSide?: 'top' | 'bottom';
|
|
76
|
+
layout?: 'auto' | 'fixed';
|
|
77
|
+
}
|
|
78
|
+
export interface TableRowProps extends ComponentPropsWithoutRef<'tr'> {
|
|
79
|
+
selected?: boolean;
|
|
80
|
+
}
|
|
81
|
+
interface TableCellLayout {
|
|
82
|
+
verticalAlign?: 'top' | 'middle' | 'bottom';
|
|
83
|
+
wrap?: boolean;
|
|
84
|
+
}
|
|
85
|
+
export type TableHeadProps = Omit<ComponentPropsWithoutRef<'th'>, 'align'> & TableCellLayout & {
|
|
86
|
+
align?: ComponentPropsWithoutRef<'th'>['align'] | 'start' | 'end';
|
|
87
|
+
};
|
|
88
|
+
export type TableCellProps = Omit<ComponentPropsWithoutRef<'td'>, 'align'> & TableCellLayout & {
|
|
89
|
+
align?: ComponentPropsWithoutRef<'td'>['align'] | 'start' | 'end';
|
|
90
|
+
};
|
|
91
|
+
export declare const Table: {
|
|
92
|
+
Container: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
93
|
+
Root: import("react").ForwardRefExoticComponent<TableProps & import("react").RefAttributes<HTMLTableElement>>;
|
|
94
|
+
Header: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "ref"> & import("react").RefAttributes<HTMLTableSectionElement>>;
|
|
95
|
+
Body: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "ref"> & import("react").RefAttributes<HTMLTableSectionElement>>;
|
|
96
|
+
Footer: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "ref"> & import("react").RefAttributes<HTMLTableSectionElement>>;
|
|
97
|
+
Row: import("react").ForwardRefExoticComponent<TableRowProps & import("react").RefAttributes<HTMLTableRowElement>>;
|
|
98
|
+
Head: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").ThHTMLAttributes<HTMLTableHeaderCellElement>, HTMLTableHeaderCellElement>, "ref">, "align"> & TableCellLayout & {
|
|
99
|
+
align?: ComponentPropsWithoutRef<"th">["align"] | "start" | "end";
|
|
100
|
+
} & import("react").RefAttributes<HTMLTableCellElement>>;
|
|
101
|
+
Cell: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").TdHTMLAttributes<HTMLTableDataCellElement>, HTMLTableDataCellElement>, "ref">, "align"> & TableCellLayout & {
|
|
102
|
+
align?: ComponentPropsWithoutRef<"td">["align"] | "start" | "end";
|
|
103
|
+
} & import("react").RefAttributes<HTMLTableCellElement>>;
|
|
104
|
+
Caption: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & import("react").RefAttributes<HTMLTableCaptionElement>>;
|
|
105
|
+
};
|
|
106
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
3
|
+
import { createContext, useContext, forwardRef, useId } from 'react';
|
|
4
|
+
import { PencilSurface } from '../PencilSurface.js';
|
|
5
|
+
import { PencilText } from '../PencilText.js';
|
|
6
|
+
import { PencilLine } from '../PencilLine.js';
|
|
7
|
+
const classes = (...values) => values.filter(Boolean).join(' ');
|
|
8
|
+
const copy = (children) => typeof children === 'string' ? _jsx(PencilText, { children: children }) : children;
|
|
9
|
+
const CardDividers = createContext(true);
|
|
10
|
+
const CardRoot = forwardRef(function CardRoot({ className, variant = 'paper', radius = 8, seed, size = 'md', divided = true, ...props }, ref) {
|
|
11
|
+
const id = useId();
|
|
12
|
+
return _jsx(CardDividers.Provider, { value: divided, children: _jsx(PencilSurface, { ...props, ref: ref, "data-size": size, className: classes('inkra-card', className), variant: variant, radius: radius, seed: seed ?? `card-${id}` }) });
|
|
13
|
+
});
|
|
14
|
+
const CardHeader = forwardRef(function CardHeader({ className, children, action, divided, padding = 'inherit', align = 'start', ...props }, ref) {
|
|
15
|
+
const inherited = useContext(CardDividers);
|
|
16
|
+
return _jsxs("div", { ...props, ref: ref, "data-padding": padding, "data-align": align, className: classes('inkra-card__header', className), children: [_jsx("div", { className: "inkra-card__heading", children: children }), action != null && _jsx("div", { className: "inkra-card__action", children: action }), (divided ?? inherited) && _jsx(PencilLine, { className: "inkra-card__divider" })] });
|
|
17
|
+
});
|
|
18
|
+
const CardTitle = forwardRef(function CardTitle({ className, children, as: Heading = 'h3', ...props }, ref) {
|
|
19
|
+
return _jsx(Heading, { ...props, ref: ref, className: classes('inkra-card__title', className), children: copy(children) });
|
|
20
|
+
});
|
|
21
|
+
const CardDescription = forwardRef(function CardDescription({ className, children, ...props }, ref) {
|
|
22
|
+
return _jsx("p", { ...props, ref: ref, className: classes('inkra-card__description', className), children: copy(children) });
|
|
23
|
+
});
|
|
24
|
+
const CardContent = forwardRef(function CardContent({ className, padding = 'inherit', ...props }, ref) {
|
|
25
|
+
return _jsx("div", { ...props, ref: ref, "data-padding": padding, className: classes('inkra-card__content', className) });
|
|
26
|
+
});
|
|
27
|
+
const CardFooter = forwardRef(function CardFooter({ className, children, divided, justify = 'start', padding = 'inherit', orientation = 'horizontal', ...props }, ref) {
|
|
28
|
+
const inherited = useContext(CardDividers);
|
|
29
|
+
return _jsxs("div", { ...props, ref: ref, "data-justify": justify, "data-padding": padding, "data-orientation": orientation, className: classes('inkra-card__footer', className), children: [(divided ?? inherited) && _jsx(PencilLine, { className: "inkra-card__divider" }), children] });
|
|
30
|
+
});
|
|
31
|
+
export const Card = { Root: CardRoot, Header: CardHeader, Title: CardTitle, Description: CardDescription, Content: CardContent, Footer: CardFooter };
|
|
32
|
+
const AlertRoot = forwardRef(function AlertRoot({ className, variant = 'info', icon, seed, style, children, role = 'status', size = 'md', appearance = 'soft', actions, ...props }, ref) {
|
|
33
|
+
const id = useId();
|
|
34
|
+
const tokens = {
|
|
35
|
+
color: `var(--inkra-${variant}-foreground)`,
|
|
36
|
+
'--inkra-paper': `var(--inkra-${variant}-surface)`,
|
|
37
|
+
'--inkra-accent': `var(--inkra-${variant}-pigment)`,
|
|
38
|
+
'--inkra-accent-strong': `var(--inkra-${variant}-foreground)`,
|
|
39
|
+
'--inkra-border-strong': `var(--inkra-${variant}-foreground)`,
|
|
40
|
+
'--inkra-border': `var(--inkra-${variant}-foreground)`,
|
|
41
|
+
...style,
|
|
42
|
+
};
|
|
43
|
+
return _jsxs(PencilSurface, { ...props, ref: ref, role: role, className: classes('inkra-alert', className), "data-variant": variant, "data-size": size, "data-appearance": appearance, variant: appearance === 'outline' ? 'outline' : 'action', radius: 8, style: tokens, seed: seed ?? `alert-${id}`, children: [icon && _jsx("span", { className: "inkra-alert__icon", "aria-hidden": "true", children: icon }), _jsxs("div", { className: "inkra-alert__body", children: [children, actions != null && _jsx("div", { className: "inkra-alert__actions", children: actions })] })] });
|
|
44
|
+
});
|
|
45
|
+
const AlertTitle = forwardRef(function AlertTitle({ className, children, ...props }, ref) {
|
|
46
|
+
return _jsx("p", { ...props, ref: ref, className: classes('inkra-alert__title', className), children: copy(children) });
|
|
47
|
+
});
|
|
48
|
+
const AlertDescription = forwardRef(function AlertDescription({ className, children, ...props }, ref) {
|
|
49
|
+
return _jsx("div", { ...props, ref: ref, className: classes('inkra-alert__description', className), children: copy(children) });
|
|
50
|
+
});
|
|
51
|
+
export const Alert = { Root: AlertRoot, Title: AlertTitle, Description: AlertDescription };
|
|
52
|
+
const AvatarRoot = forwardRef(function AvatarRoot({ className, size = 'md', radius = 8, bordered = true, style, children, ...props }, ref) {
|
|
53
|
+
const corner = Number.isFinite(radius) ? Math.max(0, Math.min(8, radius)) : 8;
|
|
54
|
+
return _jsxs(AvatarPrimitive.Root, { ...props, ref: ref, "data-size": size, "data-bordered": bordered, className: classes('inkra-avatar', className), style: { '--inkra-avatar-radius': `${corner}px`, ...style }, children: [children, bordered && _jsx(PencilSurface, { as: "span", "aria-hidden": "true", className: "inkra-avatar__outline", variant: "outline", radius: corner })] });
|
|
55
|
+
});
|
|
56
|
+
const AvatarImage = forwardRef(function AvatarImage({ className, fit = 'cover', ...props }, ref) {
|
|
57
|
+
return _jsx(AvatarPrimitive.Image, { ...props, ref: ref, "data-fit": fit, className: classes('inkra-avatar__image', className) });
|
|
58
|
+
});
|
|
59
|
+
const AvatarFallback = forwardRef(function AvatarFallback({ className, children, ...props }, ref) {
|
|
60
|
+
return _jsx(AvatarPrimitive.Fallback, { ...props, ref: ref, className: classes('inkra-avatar__fallback', className), children: copy(children) });
|
|
61
|
+
});
|
|
62
|
+
export const Avatar = { Root: AvatarRoot, Image: AvatarImage, Fallback: AvatarFallback };
|
|
63
|
+
const TableRoot = forwardRef(function TableRoot({ className, density = 'comfortable', striped = false, hoverable = false, stickyHeader = false, captionSide = 'top', layout = 'auto', ...props }, ref) {
|
|
64
|
+
return _jsx("table", { ...props, ref: ref, "data-layout": layout, "data-density": density, "data-striped": striped || undefined, "data-hoverable": hoverable || undefined, "data-sticky-header": stickyHeader || undefined, "data-caption-side": captionSide, className: classes('inkra-table', className) });
|
|
65
|
+
});
|
|
66
|
+
const TableContainer = forwardRef(function TableContainer({ className, ...props }, ref) {
|
|
67
|
+
return _jsx("div", { tabIndex: 0, ...props, ref: ref, className: classes('inkra-table-container', className) });
|
|
68
|
+
});
|
|
69
|
+
const TableHeader = forwardRef(function TableHeader(props, ref) { return _jsx("thead", { ...props, ref: ref }); });
|
|
70
|
+
const TableBody = forwardRef(function TableBody(props, ref) { return _jsx("tbody", { ...props, ref: ref }); });
|
|
71
|
+
const TableFooter = forwardRef(function TableFooter(props, ref) { return _jsx("tfoot", { ...props, ref: ref }); });
|
|
72
|
+
const TableRow = forwardRef(function TableRow({ selected = false, ...props }, ref) { return _jsx("tr", { ...props, ref: ref, "data-selected": selected || undefined }); });
|
|
73
|
+
const TableHead = forwardRef(function TableHead({ children, align = 'start', verticalAlign = 'middle', wrap = true, ...props }, ref) {
|
|
74
|
+
return _jsxs("th", { scope: "col", ...props, ref: ref, "data-align": align, "data-vertical-align": verticalAlign, "data-wrap": wrap, children: [wrap ? copy(children) : _jsx("div", { className: "inkra-table__nowrap", tabIndex: 0, children: copy(children) }), _jsx(PencilLine, { className: "inkra-table__divider" })] });
|
|
75
|
+
});
|
|
76
|
+
const TableCell = forwardRef(function TableCell({ children, align = 'start', verticalAlign = 'middle', wrap = true, ...props }, ref) {
|
|
77
|
+
return _jsxs("td", { ...props, ref: ref, "data-align": align, "data-vertical-align": verticalAlign, "data-wrap": wrap, children: [wrap ? copy(children) : _jsx("div", { className: "inkra-table__nowrap", tabIndex: 0, children: copy(children) }), _jsx(PencilLine, { className: "inkra-table__divider" })] });
|
|
78
|
+
});
|
|
79
|
+
const TableCaption = forwardRef(function TableCaption({ children, ...props }, ref) { return _jsx("caption", { ...props, ref: ref, children: copy(children) }); });
|
|
80
|
+
export const Table = { Container: TableContainer, Root: TableRoot, Header: TableHeader, Body: TableBody, Footer: TableFooter, Row: TableRow, Head: TableHead, Cell: TableCell, Caption: TableCaption };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
export interface AgendaEvent {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
/** Minutes from the selected local day's midnight. Negative/over-1440 values indicate continuation. */
|
|
6
|
+
startMinute?: number;
|
|
7
|
+
endMinute?: number;
|
|
8
|
+
description?: ReactNode;
|
|
9
|
+
kind?: 'activity' | 'travel' | 'stay';
|
|
10
|
+
color?: string;
|
|
11
|
+
icon?: ReactNode;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface DayAgendaProps extends Omit<HTMLAttributes<HTMLElement>, 'onSelect'> {
|
|
15
|
+
date: string;
|
|
16
|
+
events: readonly AgendaEvent[];
|
|
17
|
+
selectedEvent?: string;
|
|
18
|
+
onEventSelect?: (event: AgendaEvent) => void;
|
|
19
|
+
locale?: string;
|
|
20
|
+
timeZoneLabel?: string;
|
|
21
|
+
emptyLabel?: string;
|
|
22
|
+
untimedLabel?: string;
|
|
23
|
+
showOverview?: boolean;
|
|
24
|
+
hourCycle?: 'h12' | 'h23';
|
|
25
|
+
density?: 'compact' | 'comfortable';
|
|
26
|
+
showDescriptions?: boolean;
|
|
27
|
+
divided?: boolean;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
onPreviousDay?: () => void;
|
|
30
|
+
onNextDay?: () => void;
|
|
31
|
+
navigationLabels?: {
|
|
32
|
+
previous: string;
|
|
33
|
+
next: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare function agendaTime(minute: number, hourCycle?: 'h12' | 'h23', locale?: string): string;
|
|
37
|
+
export declare function agendaInterval(event: AgendaEvent): {
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
before: boolean;
|
|
41
|
+
after: boolean;
|
|
42
|
+
} | null;
|
|
43
|
+
export declare function DayAgenda({ date, events, selectedEvent, onEventSelect, locale, timeZoneLabel, emptyLabel, untimedLabel, showOverview, hourCycle, density, showDescriptions, divided, disabled, onPreviousDay, onNextDay, navigationLabels, className, ...props }: DayAgendaProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useId } from 'react';
|
|
3
|
+
import { TravelIcon } from '../internal/travelIcons.js';
|
|
4
|
+
import { Button } from '../Button.js';
|
|
5
|
+
import { createAgendaScale, layoutAgendaCards } from './layout.js';
|
|
6
|
+
import { PencilSurface } from '../PencilSurface.js';
|
|
7
|
+
import { PencilLine } from '../PencilLine.js';
|
|
8
|
+
import { PencilText } from '../PencilText.js';
|
|
9
|
+
export function agendaTime(minute, hourCycle = 'h23', locale = 'en') {
|
|
10
|
+
const value = Math.max(0, Math.min(1440, Math.floor(minute)));
|
|
11
|
+
if (hourCycle === 'h12') {
|
|
12
|
+
const time = new Date(Date.UTC(2000, 0, 1, 0, value));
|
|
13
|
+
return new Intl.DateTimeFormat(locale, { timeZone: 'UTC', hour: 'numeric', minute: '2-digit', hourCycle }).format(time) + (value === 1440 ? ' +1' : '');
|
|
14
|
+
}
|
|
15
|
+
return value === 1440 ? '00:00 +1' : `${String(Math.floor(value / 60)).padStart(2, '0')}:${String(value % 60).padStart(2, '0')}`;
|
|
16
|
+
}
|
|
17
|
+
export function agendaInterval(event) {
|
|
18
|
+
if (event.startMinute === undefined || !Number.isFinite(event.startMinute))
|
|
19
|
+
return null;
|
|
20
|
+
const end = event.endMinute;
|
|
21
|
+
if (end !== undefined && (!Number.isFinite(end) || end < event.startMinute))
|
|
22
|
+
return null;
|
|
23
|
+
if (event.startMinute >= 1440 || (end ?? event.startMinute) < 0 || (end === 0 && event.startMinute < 0))
|
|
24
|
+
return null;
|
|
25
|
+
return { start: Math.max(0, event.startMinute), end: Math.min(1440, end ?? event.startMinute), before: event.startMinute < 0, after: (end ?? 0) > 1440 };
|
|
26
|
+
}
|
|
27
|
+
export function DayAgenda({ date, events, selectedEvent, onEventSelect, locale = 'en', timeZoneLabel, emptyLabel = 'No events', untimedLabel = 'Time pending', showOverview = true, hourCycle = 'h23', density = 'comfortable', showDescriptions = true, divided = true, disabled = false, onPreviousDay, onNextDay, navigationLabels = { previous: 'Previous day', next: 'Next day' }, className, ...props }) {
|
|
28
|
+
const id = useId();
|
|
29
|
+
const validDate = /^\d{4}-\d{2}-\d{2}$/.test(date) ? new Date(`${date}T12:00:00Z`) : new Date(NaN);
|
|
30
|
+
const title = Number.isFinite(validDate.getTime()) ? new Intl.DateTimeFormat(locale, { timeZone: 'UTC', month: 'long', day: 'numeric', weekday: 'short' }).format(validDate) : date;
|
|
31
|
+
const ordered = [...events].sort((a, b) => (agendaInterval(a)?.start ?? Infinity) - (agendaInterval(b)?.start ?? Infinity));
|
|
32
|
+
const formatTime = (minute) => agendaTime(minute, hourCycle, locale);
|
|
33
|
+
const timed = ordered.flatMap(event => {
|
|
34
|
+
const interval = agendaInterval(event);
|
|
35
|
+
return interval ? [{ ...interval, id: event.id, event }] : [];
|
|
36
|
+
});
|
|
37
|
+
const intervals = timed.filter(row => row.end > row.start);
|
|
38
|
+
const points = timed.filter(row => row.end === row.start);
|
|
39
|
+
const scale = createAgendaScale(intervals, points.map(row => row.start), density === 'compact');
|
|
40
|
+
const cards = layoutAgendaCards(timed, scale).sort((a, b) => a.start - b.start);
|
|
41
|
+
const ticks = Array.from({ length: 25 }, (_, hour) => hour * 60).filter((minute, index, list) => index === 0 || index === 24 || scale.position(minute) - scale.position(list[index - 1]) >= 25);
|
|
42
|
+
const renderCard = (event, time) => _jsxs(PencilSurface, { variant: "quiet", radius: 6, className: "inkra-agenda__card", "data-selected": selectedEvent === event.id, style: { '--inkra-accent-soft': event.color ?? (event.kind === 'stay' ? '#c8c38f' : event.kind === 'travel' ? '#87bbc0' : '#a7c7ad') }, children: [onEventSelect && _jsx("button", { type: "button", className: "inkra-agenda__hit", disabled: disabled || event.disabled, "aria-label": `${time}, ${event.title}`, "aria-pressed": selectedEvent === event.id, onClick: () => onEventSelect(event) }), _jsxs("div", { className: "inkra-agenda__card-copy", children: [_jsxs("span", { className: "inkra-agenda__card-title", title: event.title, children: [event.icon && _jsx("span", { "aria-hidden": "true", children: event.icon }), _jsx(PencilText, { ellipsis: true, children: event.title })] }), showDescriptions && event.description && _jsx("span", { className: "inkra-agenda__description", children: event.description })] })] });
|
|
43
|
+
return _jsxs("section", { ...props, "data-density": density, "data-hour-cycle": hourCycle, className: ['inkra-agenda', className].filter(Boolean).join(' '), "aria-labelledby": props['aria-labelledby'] ?? id, children: [_jsxs("header", { className: "inkra-agenda__heading", children: [_jsx(PencilText, { as: "h3", id: id, children: title }), timeZoneLabel && _jsx(PencilText, { children: timeZoneLabel })] }), _jsx(PencilLine, {}), ordered.length === 0 ? _jsx(PencilText, { as: "p", children: emptyLabel }) : _jsxs(_Fragment, { children: [_jsx("div", { className: "inkra-agenda__timeline", "data-overview": showOverview, children: _jsxs("div", { className: "inkra-agenda__scale", style: { height: scale.height + 24 }, children: [ticks.map(minute => _jsxs("div", { className: "inkra-agenda__tick", style: { top: scale.position(minute) + 12 }, children: [_jsx("span", { children: _jsx(PencilText, { children: formatTime(minute) }) }), divided && _jsx(PencilLine, {})] }, minute)), _jsx("ol", { className: "inkra-agenda__lanes", children: cards.map(row => {
|
|
44
|
+
const time = `${row.before ? '\u2190 ' : ''}${formatTime(row.start)}${row.event.endMinute !== undefined ? ` - ${formatTime(row.end)}` : ''}${row.after ? ' \u2192' : ''}`;
|
|
45
|
+
return _jsxs("li", { "data-kind": row.event.kind, style: { top: row.top + 14, height: Math.max(44, row.height - 4), insetInlineStart: `${row.lane / row.lanes * 100}%`, width: `${100 / row.lanes}%` }, children: [renderCard(row.event, time), _jsx("span", { className: "inkra-agenda__accessible-time", children: time })] }, row.id);
|
|
46
|
+
}) })] }) }), ordered.some(event => !agendaInterval(event)) && _jsxs("div", { className: "inkra-agenda__pending", children: [_jsx(PencilText, { children: untimedLabel }), ordered.filter(event => !agendaInterval(event)).map(event => _jsx("div", { children: renderCard(event, untimedLabel) }, event.id))] })] }), (onPreviousDay || onNextDay) && _jsxs("footer", { className: "inkra-agenda__navigation", children: [_jsx(PencilLine, {}), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": navigationLabels.previous, title: navigationLabels.previous, disabled: !onPreviousDay, onClick: onPreviousDay, children: _jsx(TravelIcon, { name: "previous" }) }), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": navigationLabels.next, title: navigationLabels.next, disabled: !onNextDay, onClick: onNextDay, children: _jsx(TravelIcon, { name: "next" }) })] })] });
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ScheduleInterval {
|
|
2
|
+
id: string;
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function layoutAgendaIntervals<T extends ScheduleInterval>(intervals: T[]): (T & {
|
|
7
|
+
lane: number;
|
|
8
|
+
lanes: number;
|
|
9
|
+
})[];
|
|
10
|
+
export declare function createAgendaScale(intervals: ScheduleInterval[], pointTimes: number[], compact: boolean): {
|
|
11
|
+
position: (minute: number, edge?: "before" | "after") => number;
|
|
12
|
+
height: number;
|
|
13
|
+
rowHeight: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function layoutAgendaCards<T extends ScheduleInterval>(rows: T[], scale: ReturnType<typeof createAgendaScale>): (T & {
|
|
16
|
+
top: number;
|
|
17
|
+
height: number;
|
|
18
|
+
lane: number;
|
|
19
|
+
lanes: number;
|
|
20
|
+
})[];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export function layoutAgendaIntervals(intervals) {
|
|
2
|
+
const sorted = [...intervals].sort((a, b) => a.start - b.start || a.id.localeCompare(b.id));
|
|
3
|
+
const result = [];
|
|
4
|
+
let group = [], groupEnd = -Infinity, laneEnds = [];
|
|
5
|
+
const flush = () => { for (const item of group)
|
|
6
|
+
result.push({ ...item, lanes: laneEnds.length }); group = []; laneEnds = []; };
|
|
7
|
+
for (const item of sorted) {
|
|
8
|
+
if (item.start >= groupEnd)
|
|
9
|
+
flush();
|
|
10
|
+
let lane = laneEnds.findIndex(end => end <= item.start);
|
|
11
|
+
if (lane < 0)
|
|
12
|
+
lane = laneEnds.length;
|
|
13
|
+
laneEnds[lane] = item.end;
|
|
14
|
+
group.push({ ...item, lane });
|
|
15
|
+
groupEnd = Math.max(groupEnd, item.end);
|
|
16
|
+
}
|
|
17
|
+
flush();
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
export function createAgendaScale(intervals, pointTimes, compact) {
|
|
21
|
+
const rowHeight = compact ? 56 : 72;
|
|
22
|
+
const points = new Set(pointTimes);
|
|
23
|
+
const boundaries = [...new Set([0, 1440, ...pointTimes, ...intervals.flatMap(row => [row.start, row.end])])].sort((a, b) => a - b);
|
|
24
|
+
const before = new Map(), after = new Map();
|
|
25
|
+
const segments = [];
|
|
26
|
+
let height = 0;
|
|
27
|
+
for (let index = 0; index < boundaries.length; index++) {
|
|
28
|
+
const time = boundaries[index];
|
|
29
|
+
before.set(time, height);
|
|
30
|
+
if (points.has(time))
|
|
31
|
+
height += rowHeight;
|
|
32
|
+
after.set(time, height);
|
|
33
|
+
const next = boundaries[index + 1];
|
|
34
|
+
if (next === undefined)
|
|
35
|
+
continue;
|
|
36
|
+
const occupied = intervals.some(row => row.start < next && row.end > time);
|
|
37
|
+
const size = Math.max(occupied ? rowHeight : 16, (next - time) / 60 * 32);
|
|
38
|
+
segments.push({ start: time, end: next, top: height, size });
|
|
39
|
+
height += size;
|
|
40
|
+
}
|
|
41
|
+
const position = (minute, edge = 'before') => {
|
|
42
|
+
const time = Math.max(0, Math.min(1440, minute));
|
|
43
|
+
const exact = (edge === 'after' ? after : before).get(time);
|
|
44
|
+
if (exact !== undefined)
|
|
45
|
+
return exact;
|
|
46
|
+
const segment = segments.find(row => time >= row.start && time <= row.end);
|
|
47
|
+
return segment ? segment.top + (time - segment.start) / (segment.end - segment.start) * segment.size : 0;
|
|
48
|
+
};
|
|
49
|
+
return { position, height, rowHeight };
|
|
50
|
+
}
|
|
51
|
+
export function layoutAgendaCards(rows, scale) {
|
|
52
|
+
// Allocate lanes in the shared pixel scale so a point inside a long event cannot cover it.
|
|
53
|
+
const positioned = rows.map(row => {
|
|
54
|
+
const point = row.start === row.end;
|
|
55
|
+
const top = scale.position(row.start, point ? 'before' : 'after');
|
|
56
|
+
const height = point ? scale.rowHeight : scale.position(row.end) - top;
|
|
57
|
+
return { id: row.id, start: top, end: top + height, row, top, height };
|
|
58
|
+
});
|
|
59
|
+
return layoutAgendaIntervals(positioned).map(({ row, top, height, lane, lanes }) => ({ ...row, top, height, lane, lanes }));
|
|
60
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type BadgeVariant = 'neutral' | 'accent' | 'success' | 'warning' | 'danger' | 'info';
|
|
3
|
+
export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
seed?: string | number;
|
|
6
|
+
variant?: BadgeVariant;
|
|
7
|
+
size?: 'sm' | 'md' | 'lg';
|
|
8
|
+
startIcon?: ReactNode;
|
|
9
|
+
endIcon?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare const Badge: import("react").ForwardRefExoticComponent<BadgeProps & import("react").RefAttributes<HTMLSpanElement>>;
|
|
12
|
+
export type SeparatorOrientation = 'horizontal' | 'vertical';
|
|
13
|
+
export interface SeparatorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
14
|
+
weight?: number;
|
|
15
|
+
decorative?: boolean;
|
|
16
|
+
orientation?: SeparatorOrientation;
|
|
17
|
+
seed?: string | number;
|
|
18
|
+
}
|
|
19
|
+
export declare const Separator: import("react").ForwardRefExoticComponent<SeparatorProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
20
|
+
export interface SkeletonProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
21
|
+
seed?: string | number;
|
|
22
|
+
radius?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const Skeleton: import("react").ForwardRefExoticComponent<SkeletonProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
25
|
+
export interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
26
|
+
value: number | null;
|
|
27
|
+
max?: number;
|
|
28
|
+
label?: ReactNode;
|
|
29
|
+
seed?: string | number;
|
|
30
|
+
size?: 'sm' | 'md' | 'lg';
|
|
31
|
+
}
|
|
32
|
+
export declare const Progress: import("react").ForwardRefExoticComponent<ProgressProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useId } from 'react';
|
|
3
|
+
import { PencilLine } from '../PencilLine.js';
|
|
4
|
+
import { PencilSurface } from '../PencilSurface.js';
|
|
5
|
+
import { PencilText } from '../PencilText.js';
|
|
6
|
+
const badgeTokens = {
|
|
7
|
+
neutral: { foreground: 'ink-muted', pigment: 'surface-muted' },
|
|
8
|
+
accent: { foreground: 'accent-strong', pigment: 'accent-soft' },
|
|
9
|
+
success: { foreground: 'success-foreground', pigment: 'success-pigment' },
|
|
10
|
+
warning: { foreground: 'warning-foreground', pigment: 'warning-pigment' },
|
|
11
|
+
danger: { foreground: 'danger-foreground', pigment: 'danger-pigment' },
|
|
12
|
+
info: { foreground: 'info-foreground', pigment: 'info-pigment' },
|
|
13
|
+
};
|
|
14
|
+
export const Badge = forwardRef(function Badge({ children, className, seed, style, variant = 'neutral', size = 'md', startIcon, endIcon, ...props }, ref) {
|
|
15
|
+
const generatedId = useId();
|
|
16
|
+
const tokens = badgeTokens[variant];
|
|
17
|
+
const resolvedStyle = {
|
|
18
|
+
...style,
|
|
19
|
+
color: `var(--inkra-${tokens.foreground})`,
|
|
20
|
+
'--inkra-coral-soft': `var(--inkra-${tokens.pigment})`,
|
|
21
|
+
'--inkra-border-strong': `var(--inkra-${tokens.foreground})`,
|
|
22
|
+
};
|
|
23
|
+
return (_jsxs(PencilSurface, { ...props, as: "span", className: ['inkra-badge', className].filter(Boolean).join(' '), "data-variant": variant, "data-size": size, radius: 6, ref: ref, seed: seed ?? `inkra-badge-${generatedId}`, style: resolvedStyle, variant: "badge", children: [startIcon && _jsx("span", { className: "inkra-badge__icon", "aria-hidden": "true", children: startIcon }), typeof children === 'string' ? (_jsx(PencilText, { seed: `${seed ?? `inkra-badge-${generatedId}`}-label`, children: children })) : children, endIcon && _jsx("span", { className: "inkra-badge__icon", "aria-hidden": "true", children: endIcon })] }));
|
|
24
|
+
});
|
|
25
|
+
export const Separator = forwardRef(function Separator({ className, decorative = false, orientation = 'horizontal', weight = 0.9, seed, ...props }, ref) {
|
|
26
|
+
const semanticProps = decorative
|
|
27
|
+
? { 'aria-hidden': true }
|
|
28
|
+
: { 'aria-orientation': orientation, role: 'separator' };
|
|
29
|
+
return (_jsx("div", { ...props, ...semanticProps, className: ['inkra-separator', className].filter(Boolean).join(' '), "data-orientation": orientation, ref: ref, children: _jsx(PencilLine, { className: "inkra-separator__line", orientation: orientation, seed: seed ?? `inkra-separator-${orientation}`, weight: Number.isFinite(weight) ? Math.max(0.3, Math.min(2, weight)) : 0.9 }) }));
|
|
30
|
+
});
|
|
31
|
+
export const Skeleton = forwardRef(function Skeleton({ className, seed = 'inkra-skeleton', radius, ...props }, ref) {
|
|
32
|
+
return (_jsx(PencilSurface, { ...props, "aria-hidden": "true", as: "div", className: ['inkra-skeleton', className].filter(Boolean).join(' '), ref: ref, seed: seed, radius: radius, variant: "quiet" }));
|
|
33
|
+
});
|
|
34
|
+
function normalizeMax(max) {
|
|
35
|
+
return typeof max === 'number' && Number.isFinite(max) && max > 0 ? max : 100;
|
|
36
|
+
}
|
|
37
|
+
function normalizeValue(value, max) {
|
|
38
|
+
if (value === null)
|
|
39
|
+
return null;
|
|
40
|
+
if (!Number.isFinite(value))
|
|
41
|
+
return 0;
|
|
42
|
+
return Math.min(max, Math.max(0, value));
|
|
43
|
+
}
|
|
44
|
+
export const Progress = forwardRef(function Progress({ 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, label, max, seed, style, value, size = 'md', ...props }, ref) {
|
|
45
|
+
const generatedId = useId();
|
|
46
|
+
const labelId = `inkra-progress-${generatedId}-label`;
|
|
47
|
+
const resolvedMax = normalizeMax(max);
|
|
48
|
+
const resolvedValue = normalizeValue(value, resolvedMax);
|
|
49
|
+
const percent = resolvedValue === null ? null : resolvedValue / resolvedMax * 100;
|
|
50
|
+
const resolvedLabelledBy = ariaLabel == null && ariaLabelledBy == null && label != null
|
|
51
|
+
? labelId
|
|
52
|
+
: ariaLabelledBy;
|
|
53
|
+
const resolvedSeed = seed ?? `inkra-progress-${generatedId}`;
|
|
54
|
+
const resolvedStyle = {
|
|
55
|
+
...style,
|
|
56
|
+
'--inkra-progress-value': `${percent ?? 36}%`,
|
|
57
|
+
};
|
|
58
|
+
return (_jsxs("div", { ...props, "aria-label": ariaLabel, "aria-labelledby": resolvedLabelledBy, "aria-valuemax": resolvedMax, "aria-valuemin": 0, "aria-valuenow": resolvedValue ?? undefined, className: ['inkra-progress', className].filter(Boolean).join(' '), "data-state": resolvedValue === null ? 'indeterminate' : 'determinate', "data-value": resolvedValue ?? undefined, "data-size": size, ref: ref, role: "progressbar", style: resolvedStyle, children: [label == null ? null : (typeof label === 'string' ? (_jsx(PencilText, { as: "span", className: "inkra-progress__label", id: labelId, seed: `${resolvedSeed}-label`, children: label })) : _jsx("span", { className: "inkra-progress__label", id: labelId, children: label })), _jsxs("span", { "aria-hidden": "true", className: "inkra-progress__track", children: [_jsx(PencilSurface, { as: "span", className: "inkra-progress__outline", radius: 6, seed: `${resolvedSeed}-outline`, variant: "outline" }), _jsx("span", { className: "inkra-progress__fill-clip", children: _jsx(PencilSurface, { as: "span", className: "inkra-progress__fill", radius: 6, seed: `${resolvedSeed}-fill`, variant: "selection" }) })] })] }));
|
|
59
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as Primitive from '@radix-ui/react-dropdown-menu';
|
|
2
|
+
import { type ReactNode } from 'react';
|
|
3
|
+
export type DropdownMenuProps = Primitive.DropdownMenuProps;
|
|
4
|
+
declare function Root(props: DropdownMenuProps): import("react").JSX.Element;
|
|
5
|
+
export type DropdownMenuTriggerProps = Primitive.DropdownMenuTriggerProps;
|
|
6
|
+
export type DropdownMenuPortalProps = Primitive.DropdownMenuPortalProps;
|
|
7
|
+
declare function Portal({ children, ...props }: DropdownMenuPortalProps): import("react").JSX.Element;
|
|
8
|
+
export interface DropdownMenuContentProps extends Omit<Primitive.DropdownMenuContentProps, 'asChild'> {
|
|
9
|
+
seed?: string | number;
|
|
10
|
+
}
|
|
11
|
+
export interface DropdownMenuItemProps extends Omit<Primitive.DropdownMenuItemProps, 'asChild'> {
|
|
12
|
+
destructive?: boolean;
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export type DropdownMenuCheckboxItemProps = Omit<Primitive.DropdownMenuCheckboxItemProps, 'asChild'>;
|
|
16
|
+
export type DropdownMenuRadioItemProps = Omit<Primitive.DropdownMenuRadioItemProps, 'asChild'>;
|
|
17
|
+
export type DropdownMenuLabelProps = Omit<Primitive.DropdownMenuLabelProps, 'asChild'>;
|
|
18
|
+
export type DropdownMenuSeparatorProps = Omit<Primitive.DropdownMenuSeparatorProps, 'asChild' | 'children'>;
|
|
19
|
+
export type DropdownMenuGroupProps = Primitive.DropdownMenuGroupProps;
|
|
20
|
+
export type DropdownMenuRadioGroupProps = Primitive.DropdownMenuRadioGroupProps;
|
|
21
|
+
export declare const DropdownMenu: {
|
|
22
|
+
Root: typeof Root;
|
|
23
|
+
Trigger: import("react").ForwardRefExoticComponent<Primitive.DropdownMenuTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
24
|
+
Portal: typeof Portal;
|
|
25
|
+
Content: import("react").ForwardRefExoticComponent<DropdownMenuContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
26
|
+
Item: import("react").ForwardRefExoticComponent<DropdownMenuItemProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
27
|
+
CheckboxItem: import("react").ForwardRefExoticComponent<DropdownMenuCheckboxItemProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
28
|
+
RadioItem: import("react").ForwardRefExoticComponent<DropdownMenuRadioItemProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
29
|
+
Label: import("react").ForwardRefExoticComponent<DropdownMenuLabelProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
30
|
+
Separator: import("react").ForwardRefExoticComponent<DropdownMenuSeparatorProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
31
|
+
Group: import("react").ForwardRefExoticComponent<Primitive.DropdownMenuGroupProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
32
|
+
RadioGroup: import("react").ForwardRefExoticComponent<Primitive.DropdownMenuRadioGroupProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
33
|
+
};
|
|
34
|
+
export {};
|