@hackcove/ui 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -4
- package/dist/AppShell.d.ts +37 -0
- package/dist/AppShell.js +61 -0
- package/dist/Avatar.d.ts +9 -4
- package/dist/Avatar.js +9 -3
- package/dist/BulletList.d.ts +3 -0
- package/dist/BulletList.js +6 -0
- package/dist/Code.d.ts +3 -0
- package/dist/Code.js +6 -0
- package/dist/ColourSchemeToggle.d.ts +7 -0
- package/dist/ColourSchemeToggle.js +25 -0
- package/dist/Container.d.ts +12 -0
- package/dist/Container.js +9 -0
- package/dist/DateCalendar.d.ts +4 -0
- package/dist/DateCalendar.js +40 -0
- package/dist/DateField.d.ts +49 -0
- package/dist/DateField.js +77 -0
- package/dist/DatePicker.d.ts +8 -0
- package/dist/DatePicker.js +27 -0
- package/dist/Divider.d.ts +3 -0
- package/dist/Divider.js +6 -0
- package/dist/InlineLinks.d.ts +11 -0
- package/dist/InlineLinks.js +11 -0
- package/dist/Markdown.js +1 -1
- package/dist/PageHeader.d.ts +19 -0
- package/dist/PageHeader.js +11 -0
- package/dist/PageLayouts.d.ts +73 -0
- package/dist/PageLayouts.js +63 -0
- package/dist/Stack.d.ts +30 -0
- package/dist/Stack.js +28 -0
- package/dist/TextLink.d.ts +12 -0
- package/dist/TextLink.js +8 -0
- package/dist/Video.d.ts +10 -0
- package/dist/Video.js +10 -0
- package/dist/colourScheme.d.ts +12 -0
- package/dist/colourScheme.js +40 -0
- package/dist/index.d.ts +18 -1
- package/dist/index.js +16 -0
- package/dist/isoDate.d.ts +5 -0
- package/dist/isoDate.js +16 -0
- package/dist/shownDate.d.ts +45 -0
- package/dist/shownDate.js +88 -0
- package/dist/typography.d.ts +32 -24
- package/dist/typography.js +39 -9
- package/dist/ui.d.ts +1 -0
- package/dist/ui.js +3 -1
- package/package.json +24 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CalendarDate } from "@internationalized/date";
|
|
2
|
+
import { type FocusEvent, type ReactElement } from "react";
|
|
3
|
+
import type { DateFieldProps, Read } from "./DateField.js";
|
|
4
|
+
type ValueKeys = "value" | "defaultValue" | "onChange" | "minValue" | "maxValue" | "isRequired";
|
|
5
|
+
/** The value props, each of which may be passed as `undefined`. */
|
|
6
|
+
type ValueProps = {
|
|
7
|
+
[K in ValueKeys]?: DateFieldProps[K] | undefined;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The value the field reports is always what it shows: the typed date when it is complete, exists
|
|
11
|
+
* and is within min/max, else `null`. Two parts of React Aria disagree with that, so this owns both:
|
|
12
|
+
*
|
|
13
|
+
* - **The value.** React Aria keeps its last valid date behind an impossible or partly cleared
|
|
14
|
+
* display, and reports an out-of-range one. So the consumer's `onChange` is fired from what the
|
|
15
|
+
* segments read, once per change: a valid date turning invalid reports `null`. React Aria itself
|
|
16
|
+
* is controlled by `inner`, so a parent holding that `null` does not wipe the typed segments; a
|
|
17
|
+
* `value` the parent sets that differs from the last report is passed through, and not reported
|
|
18
|
+
* back. Because React Aria's own value goes stale, `validate` checks `isRequired` against the
|
|
19
|
+
* segments: a partly filled required field blocks the form.
|
|
20
|
+
* - **Keeping an impossible date.** When focus leaves a complete field, React Aria moves an
|
|
21
|
+
* impossible day to the month's last and reports that date (`confirmPlaceholder`); it skips this
|
|
22
|
+
* for a read-only field. So while the typed date is impossible, the field is read-only for exactly
|
|
23
|
+
* the blur that leaves it: `onBlurCapture` on a wrapper of the input turns it on before React
|
|
24
|
+
* Aria's blur handler runs, and the field's own `onBlur`, which runs after it, turns it off again.
|
|
25
|
+
*
|
|
26
|
+
* `shown` (`YYYY-MM-DD` or `""`) is what the hidden `name` input posts.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useShownDate(props: ValueProps): {
|
|
29
|
+
inner: CalendarDate | null;
|
|
30
|
+
setInner: import("react").Dispatch<import("react").SetStateAction<CalendarDate | null>>;
|
|
31
|
+
shown: string;
|
|
32
|
+
impossible: string | null;
|
|
33
|
+
onRead: (next: Read) => void;
|
|
34
|
+
validate: () => "Enter the whole date." | null;
|
|
35
|
+
leaving: boolean;
|
|
36
|
+
onBlurCapture: (event: FocusEvent<HTMLElement>) => void;
|
|
37
|
+
onLeft: () => void;
|
|
38
|
+
};
|
|
39
|
+
/** The hidden input a form posts under `name`: the shown date as `YYYY-MM-DD`, or `""`. */
|
|
40
|
+
export declare function ShownInput({ name, shown, isDisabled, }: {
|
|
41
|
+
name: string | undefined;
|
|
42
|
+
shown: string;
|
|
43
|
+
isDisabled: boolean | undefined;
|
|
44
|
+
}): ReactElement | null;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState, } from "react";
|
|
3
|
+
import { flushSync } from "react-dom";
|
|
4
|
+
import { fromISODate, toISODate } from "./isoDate.js";
|
|
5
|
+
/** `iso` when it is a date within min/max, else `""`. */
|
|
6
|
+
function withinRange(iso, { minValue, maxValue }) {
|
|
7
|
+
const date = fromISODate(iso);
|
|
8
|
+
if (!date)
|
|
9
|
+
return "";
|
|
10
|
+
if (minValue && date.compare(minValue) < 0)
|
|
11
|
+
return "";
|
|
12
|
+
if (maxValue && date.compare(maxValue) > 0)
|
|
13
|
+
return "";
|
|
14
|
+
return iso;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The value the field reports is always what it shows: the typed date when it is complete, exists
|
|
18
|
+
* and is within min/max, else `null`. Two parts of React Aria disagree with that, so this owns both:
|
|
19
|
+
*
|
|
20
|
+
* - **The value.** React Aria keeps its last valid date behind an impossible or partly cleared
|
|
21
|
+
* display, and reports an out-of-range one. So the consumer's `onChange` is fired from what the
|
|
22
|
+
* segments read, once per change: a valid date turning invalid reports `null`. React Aria itself
|
|
23
|
+
* is controlled by `inner`, so a parent holding that `null` does not wipe the typed segments; a
|
|
24
|
+
* `value` the parent sets that differs from the last report is passed through, and not reported
|
|
25
|
+
* back. Because React Aria's own value goes stale, `validate` checks `isRequired` against the
|
|
26
|
+
* segments: a partly filled required field blocks the form.
|
|
27
|
+
* - **Keeping an impossible date.** When focus leaves a complete field, React Aria moves an
|
|
28
|
+
* impossible day to the month's last and reports that date (`confirmPlaceholder`); it skips this
|
|
29
|
+
* for a read-only field. So while the typed date is impossible, the field is read-only for exactly
|
|
30
|
+
* the blur that leaves it: `onBlurCapture` on a wrapper of the input turns it on before React
|
|
31
|
+
* Aria's blur handler runs, and the field's own `onBlur`, which runs after it, turns it off again.
|
|
32
|
+
*
|
|
33
|
+
* `shown` (`YYYY-MM-DD` or `""`) is what the hidden `name` input posts.
|
|
34
|
+
*/
|
|
35
|
+
export function useShownDate(props) {
|
|
36
|
+
const { value, defaultValue, onChange, isRequired } = props;
|
|
37
|
+
const [inner, setInner] = useState(value ?? defaultValue ?? null);
|
|
38
|
+
const [read, setRead] = useState({
|
|
39
|
+
typed: toISODate(inner),
|
|
40
|
+
impossible: null,
|
|
41
|
+
partial: false,
|
|
42
|
+
});
|
|
43
|
+
const [leaving, setLeaving] = useState(false);
|
|
44
|
+
const shown = withinRange(read.typed, props);
|
|
45
|
+
const reported = useRef(shown);
|
|
46
|
+
const report = useRef(onChange);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
report.current = onChange;
|
|
49
|
+
});
|
|
50
|
+
const given = value === undefined ? undefined : toISODate(value);
|
|
51
|
+
const givenShown = withinRange(given ?? "", props);
|
|
52
|
+
const lastGiven = useRef(given);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (given === lastGiven.current)
|
|
55
|
+
return;
|
|
56
|
+
lastGiven.current = given;
|
|
57
|
+
if (given === undefined || given === reported.current)
|
|
58
|
+
return;
|
|
59
|
+
reported.current = givenShown;
|
|
60
|
+
setInner(fromISODate(given));
|
|
61
|
+
}, [given, givenShown]);
|
|
62
|
+
const onRead = useCallback((next) => setRead(next), []);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (shown === reported.current)
|
|
65
|
+
return;
|
|
66
|
+
reported.current = shown;
|
|
67
|
+
report.current?.(fromISODate(shown));
|
|
68
|
+
}, [shown]);
|
|
69
|
+
return {
|
|
70
|
+
inner,
|
|
71
|
+
setInner,
|
|
72
|
+
shown,
|
|
73
|
+
impossible: read.impossible,
|
|
74
|
+
onRead,
|
|
75
|
+
validate: () => (isRequired && read.partial ? "Enter the whole date." : null),
|
|
76
|
+
leaving,
|
|
77
|
+
onBlurCapture: (event) => {
|
|
78
|
+
if (read.impossible && !event.currentTarget.contains(event.relatedTarget)) {
|
|
79
|
+
flushSync(() => setLeaving(true));
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
onLeft: () => setLeaving(false),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** The hidden input a form posts under `name`: the shown date as `YYYY-MM-DD`, or `""`. */
|
|
86
|
+
export function ShownInput({ name, shown, isDisabled, }) {
|
|
87
|
+
return name ? _jsx("input", { type: "hidden", name: name, value: shown, disabled: isDisabled }) : null;
|
|
88
|
+
}
|
package/dist/typography.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef, ElementType, ReactNode } from "react";
|
|
1
|
+
import type { ComponentPropsWithoutRef, ElementType, ReactElement, ReactNode } from "react";
|
|
2
2
|
export type TypographyColor = "default" | "secondary" | "tertiary" | "muted" | "brand";
|
|
3
3
|
/** Own props shared by every typography component; the rest follow the rendered element. */
|
|
4
4
|
type OwnProps = {
|
|
@@ -19,57 +19,65 @@ export type TypographyProps<E extends ElementType> = OwnProps & {
|
|
|
19
19
|
* overriding PageHeading's size.
|
|
20
20
|
*/
|
|
21
21
|
export declare const Display: {
|
|
22
|
-
<E extends ElementType = "h1">(
|
|
22
|
+
<E extends ElementType = "h1">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
23
23
|
displayName: string;
|
|
24
24
|
};
|
|
25
25
|
/** The supporting sentence under a `Display`. `p`, text-lg/7 normal, secondary. */
|
|
26
26
|
export declare const Lead: {
|
|
27
|
-
<E extends ElementType = "p">(
|
|
27
|
+
<E extends ElementType = "p">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
28
28
|
displayName: string;
|
|
29
29
|
};
|
|
30
30
|
/** Page title. `h1`, text-2xl/8 semibold, primary text. */
|
|
31
31
|
export declare const PageHeading: {
|
|
32
|
-
<E extends ElementType = "h1">(
|
|
33
|
-
displayName: string;
|
|
34
|
-
};
|
|
35
|
-
/** Top-level section header. `h2`, text-base/6 semibold, primary text. */
|
|
36
|
-
export declare const SectionHeading: {
|
|
37
|
-
<E extends ElementType = "h2">({ as, color, className, children, ...rest }: TypographyProps<E>): import("react").JSX.Element;
|
|
38
|
-
displayName: string;
|
|
39
|
-
};
|
|
40
|
-
/** Nested header. `h3`, text-sm/5 semibold, primary text. */
|
|
41
|
-
export declare const SubsectionHeading: {
|
|
42
|
-
<E extends ElementType = "h3">({ as, color, className, children, ...rest }: TypographyProps<E>): import("react").JSX.Element;
|
|
32
|
+
<E extends ElementType = "h1">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
43
33
|
displayName: string;
|
|
44
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Top-level section header. `h2`, text-base/6 semibold, primary text. `rule` sets
|
|
37
|
+
* a hairline under it (the `Divider` line colour) with the space either side of
|
|
38
|
+
* the line built in.
|
|
39
|
+
*/
|
|
40
|
+
export declare function SectionHeading<E extends ElementType = "h2">({ rule, ...props }: TypographyProps<E> & {
|
|
41
|
+
rule?: boolean;
|
|
42
|
+
}): ReactElement;
|
|
43
|
+
export type SubsectionHeadingSize = "sm" | "base" | "lg";
|
|
44
|
+
/**
|
|
45
|
+
* Nested header. `h3`, text-sm/5 semibold, primary text. `size` steps it up for
|
|
46
|
+
* a card, drawer or form-group title: `sm` (default), `base` (bold) or `lg`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function SubsectionHeading<E extends ElementType = "h3">({ size, ...props }: TypographyProps<E> & {
|
|
49
|
+
size?: SubsectionHeadingSize;
|
|
50
|
+
}): ReactElement;
|
|
45
51
|
/** Dialog/modal title. `h2`, text-base/6 semibold, primary text. */
|
|
46
52
|
export declare const ModalHeading: {
|
|
47
|
-
<E extends ElementType = "h2">(
|
|
53
|
+
<E extends ElementType = "h2">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
48
54
|
displayName: string;
|
|
49
55
|
};
|
|
50
56
|
/** Supporting line under a heading. `p`, text-sm/5 normal, secondary. */
|
|
51
57
|
export declare const Subtitle: {
|
|
52
|
-
<E extends ElementType = "p">(
|
|
58
|
+
<E extends ElementType = "p">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
53
59
|
displayName: string;
|
|
54
60
|
};
|
|
55
61
|
/** Small all-caps label above a group. `span`, text-xs semibold uppercase, tertiary. */
|
|
56
62
|
export declare const Overline: {
|
|
57
|
-
<E extends ElementType = "span">(
|
|
58
|
-
displayName: string;
|
|
59
|
-
};
|
|
60
|
-
/** Default running text. `span` (inline; `as="p"` for a paragraph), text-sm/5 normal, secondary. */
|
|
61
|
-
export declare const Body: {
|
|
62
|
-
<E extends ElementType = "span">({ as, color, className, children, ...rest }: TypographyProps<E>): import("react").JSX.Element;
|
|
63
|
+
<E extends ElementType = "span">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
63
64
|
displayName: string;
|
|
64
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Default running text. `span` (inline; `as="p"` for a paragraph), text-sm/5 normal, secondary.
|
|
68
|
+
* `preserveNewlines` keeps the line breaks in the text (a user-typed note); runs of spaces still collapse.
|
|
69
|
+
*/
|
|
70
|
+
export declare function Body<E extends ElementType = "span">({ preserveNewlines, ...props }: TypographyProps<E> & {
|
|
71
|
+
preserveNewlines?: boolean;
|
|
72
|
+
}): ReactElement;
|
|
65
73
|
/** Emphasised run of body text. `span`, text-sm/5 medium, primary text. */
|
|
66
74
|
export declare const BodyStrong: {
|
|
67
|
-
<E extends ElementType = "span">(
|
|
75
|
+
<E extends ElementType = "span">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
68
76
|
displayName: string;
|
|
69
77
|
};
|
|
70
78
|
/** Fine print / metadata. `span` (inline; `as="p"` for a block), text-xs/4 normal, tertiary. */
|
|
71
79
|
export declare const Caption: {
|
|
72
|
-
<E extends ElementType = "span">(
|
|
80
|
+
<E extends ElementType = "span">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
73
81
|
displayName: string;
|
|
74
82
|
};
|
|
75
83
|
export {};
|
package/dist/typography.js
CHANGED
|
@@ -15,13 +15,20 @@ const COLOR = {
|
|
|
15
15
|
* layout classes — never the pinned size/weight.
|
|
16
16
|
*/
|
|
17
17
|
function typography(displayName, defaultAs, variantClass, defaultColor) {
|
|
18
|
-
function Typography(
|
|
19
|
-
|
|
20
|
-
return (_jsx(Tag, { className: cx(variantClass, COLOR[color ?? defaultColor], className), ...rest, children: children }));
|
|
18
|
+
function Typography(props) {
|
|
19
|
+
return pinned(defaultAs, variantClass, defaultColor, props);
|
|
21
20
|
}
|
|
22
21
|
Typography.displayName = displayName;
|
|
23
22
|
return Typography;
|
|
24
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* The one place a pinned role renders. The few roles with an opt-in prop of their own are
|
|
26
|
+
* written by hand, not by `typography`, and call this too.
|
|
27
|
+
*/
|
|
28
|
+
function pinned(defaultAs, variantClass, defaultColor, { as, color, className, children, ...rest }) {
|
|
29
|
+
const Tag = as ?? defaultAs;
|
|
30
|
+
return (_jsx(Tag, { className: cx(variantClass, COLOR[color ?? defaultColor], className), ...rest, children: children }));
|
|
31
|
+
}
|
|
25
32
|
// --- Structural roles (block by default) -----------------------------------
|
|
26
33
|
/**
|
|
27
34
|
* Marketing-scale headline — the one line at the top of a public page. `h1`,
|
|
@@ -35,10 +42,27 @@ export const Display = typography("Display", "h1", "text-4xl/[1.1] font-semibold
|
|
|
35
42
|
export const Lead = typography("Lead", "p", "text-lg/7 font-normal sm:text-xl/8", "secondary");
|
|
36
43
|
/** Page title. `h1`, text-2xl/8 semibold, primary text. */
|
|
37
44
|
export const PageHeading = typography("PageHeading", "h1", "text-2xl/8 font-semibold tracking-tight", "default");
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Top-level section header. `h2`, text-base/6 semibold, primary text. `rule` sets
|
|
47
|
+
* a hairline under it (the `Divider` line colour) with the space either side of
|
|
48
|
+
* the line built in.
|
|
49
|
+
*/
|
|
50
|
+
export function SectionHeading({ rule, ...props }) {
|
|
51
|
+
const variant = cx(rule && "mb-4 border-b border-slate-200/70 pb-2", "text-base/6 font-semibold");
|
|
52
|
+
return pinned("h2", variant, "default", props);
|
|
53
|
+
}
|
|
54
|
+
const SUBSECTION_SIZE = {
|
|
55
|
+
sm: "text-sm/5 font-semibold",
|
|
56
|
+
base: "text-base/6 font-bold",
|
|
57
|
+
lg: "text-lg/7 font-semibold",
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Nested header. `h3`, text-sm/5 semibold, primary text. `size` steps it up for
|
|
61
|
+
* a card, drawer or form-group title: `sm` (default), `base` (bold) or `lg`.
|
|
62
|
+
*/
|
|
63
|
+
export function SubsectionHeading({ size = "sm", ...props }) {
|
|
64
|
+
return pinned("h3", SUBSECTION_SIZE[size], "default", props);
|
|
65
|
+
}
|
|
42
66
|
/** Dialog/modal title. `h2`, text-base/6 semibold, primary text. */
|
|
43
67
|
export const ModalHeading = typography("ModalHeading", "h2", "text-base/6 font-semibold", "default");
|
|
44
68
|
/** Supporting line under a heading. `p`, text-sm/5 normal, secondary. */
|
|
@@ -46,8 +70,14 @@ export const Subtitle = typography("Subtitle", "p", "text-sm/5 font-normal", "se
|
|
|
46
70
|
// --- Inline roles (inline by default) --------------------------------------
|
|
47
71
|
/** Small all-caps label above a group. `span`, text-xs semibold uppercase, tertiary. */
|
|
48
72
|
export const Overline = typography("Overline", "span", "text-xs font-semibold uppercase tracking-wide", "tertiary");
|
|
49
|
-
/**
|
|
50
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Default running text. `span` (inline; `as="p"` for a paragraph), text-sm/5 normal, secondary.
|
|
75
|
+
* `preserveNewlines` keeps the line breaks in the text (a user-typed note); runs of spaces still collapse.
|
|
76
|
+
*/
|
|
77
|
+
export function Body({ preserveNewlines, ...props }) {
|
|
78
|
+
const variant = cx(preserveNewlines && "whitespace-pre-line", "text-sm/5 font-normal");
|
|
79
|
+
return pinned("span", variant, "secondary", props);
|
|
80
|
+
}
|
|
51
81
|
/** Emphasised run of body text. `span`, text-sm/5 medium, primary text. */
|
|
52
82
|
export const BodyStrong = typography("BodyStrong", "span", "text-sm/5 font-medium", "default");
|
|
53
83
|
/** Fine print / metadata. `span` (inline; `as="p"` for a block), text-xs/4 normal, tertiary. */
|
package/dist/ui.d.ts
CHANGED
package/dist/ui.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from "./cx.js";
|
|
3
|
+
import { PageHeaderContent } from "./PageHeader.js";
|
|
3
4
|
// Small presentational primitives written against Tailwind's slate-based class vocabulary
|
|
4
5
|
// (remapped to Catppuccin Mocha in dark mode by theme.css).
|
|
6
|
+
/** @deprecated use PageHeader */
|
|
5
7
|
export function PageTitle({ title, subtitle }) {
|
|
6
|
-
return
|
|
8
|
+
return _jsx(PageHeaderContent, { title: title, subtitle: subtitle });
|
|
7
9
|
}
|
|
8
10
|
/** A bordered panel with an optional title and count; `as` picks the element (default `section`). */
|
|
9
11
|
export function Card({ title, count, as: Tag = "section", className, children, }) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hackcove/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Hack Cove React components: primitives, typography roles and a safe Markdown renderer, written against Tailwind v4 utilities. Pair with a @hackcove/theme-* package.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"components",
|
|
7
|
+
"design-system",
|
|
8
|
+
"hackcove",
|
|
9
|
+
"markdown",
|
|
10
|
+
"react",
|
|
11
|
+
"tailwind",
|
|
12
|
+
"tailwindcss",
|
|
13
|
+
"ui"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/madangryscientist/hackcove/tree/main/packages/ui#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/madangryscientist/hackcove/issues"
|
|
18
|
+
},
|
|
5
19
|
"license": "MIT",
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Jacobus Langner",
|
|
22
|
+
"url": "https://github.com/madangryscientist"
|
|
23
|
+
},
|
|
6
24
|
"repository": {
|
|
7
25
|
"type": "git",
|
|
8
26
|
"url": "git+https://github.com/madangryscientist/hackcove.git",
|
|
@@ -29,6 +47,10 @@
|
|
|
29
47
|
"pack-check": "npm pack --dry-run",
|
|
30
48
|
"prepack": "bun run build"
|
|
31
49
|
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@internationalized/date": "^3.12.4",
|
|
52
|
+
"react-aria-components": "^1.22.1"
|
|
53
|
+
},
|
|
32
54
|
"devDependencies": {
|
|
33
55
|
"@types/bun": "1.4.3",
|
|
34
56
|
"@types/react": "^19.3.0",
|
|
@@ -41,6 +63,7 @@
|
|
|
41
63
|
},
|
|
42
64
|
"peerDependencies": {
|
|
43
65
|
"react": ">=18",
|
|
66
|
+
"react-dom": ">=18",
|
|
44
67
|
"tailwindcss": "^4"
|
|
45
68
|
},
|
|
46
69
|
"nx": {
|