@astra-kit/ui 1.0.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +14 -3
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/components/button-link.d.ts +15 -0
  5. package/dist/components/button-link.js +70 -0
  6. package/dist/components/button-recipe.d.ts +27 -0
  7. package/dist/components/button-recipe.js +44 -0
  8. package/dist/components/button.d.ts +3 -5
  9. package/dist/components/button.js +1 -25
  10. package/dist/components/empty-state.d.ts +20 -0
  11. package/dist/components/empty-state.js +357 -0
  12. package/dist/components/metric-card.d.ts +22 -0
  13. package/dist/components/metric-card.js +378 -0
  14. package/dist/components/radio-group.d.ts +5 -3
  15. package/dist/components/radio-group.js +88 -85
  16. package/dist/components/stepper.d.ts +39 -0
  17. package/dist/components/stepper.js +693 -0
  18. package/dist/components/timeline.d.ts +51 -0
  19. package/dist/components/timeline.js +1013 -0
  20. package/dist/components/usage-meter.d.ts +39 -0
  21. package/dist/components/usage-meter.js +1093 -0
  22. package/dist/constants/empty-state.d.ts +12 -0
  23. package/dist/constants/empty-state.js +12 -0
  24. package/dist/constants/metric-card.d.ts +12 -0
  25. package/dist/constants/metric-card.js +12 -0
  26. package/dist/constants/stepper.d.ts +52 -0
  27. package/dist/constants/stepper.js +23 -0
  28. package/dist/constants/timeline.d.ts +62 -0
  29. package/dist/constants/timeline.js +31 -0
  30. package/dist/constants/usage-meter.d.ts +100 -0
  31. package/dist/constants/usage-meter.js +38 -0
  32. package/dist/hooks/use-has-entered-view.d.ts +9 -0
  33. package/dist/hooks/use-has-entered-view.js +46 -0
  34. package/dist/index.d.ts +7 -0
  35. package/dist/index.js +8 -0
  36. package/dist/motion/arc-odometer.d.ts +53 -0
  37. package/dist/motion/arc-odometer.js +424 -0
  38. package/dist/motion/arc-text-swap.d.ts +22 -0
  39. package/dist/motion/arc-text-swap.js +142 -0
  40. package/dist/motion/arc-tokens.d.ts +1 -0
  41. package/dist/motion/arc-tokens.js +2 -1
  42. package/dist/styles.css +1 -1
  43. package/package.json +31 -1
@@ -0,0 +1,12 @@
1
+ /** Tuning of Arc's EmptyState, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** Size, in pixels, of the default folder icon. */
3
+ export declare const EMPTY_STATE_ICON_SIZE_PX = 24;
4
+ /** Stroke width of the default folder icon. */
5
+ export declare const EMPTY_STATE_ICON_STROKE_WIDTH = 1.5;
6
+ /** Scale an incoming icon pops from. */
7
+ export declare const EMPTY_STATE_ICON_ENTER_SCALE = 0.6;
8
+ /**
9
+ * Window, in milliseconds, after new copy arrives in which a height change springs; later resizes (fonts, container
10
+ * width) follow instantly.
11
+ */
12
+ export declare const EMPTY_STATE_HEIGHT_MORPH_WINDOW_MS = 120;
@@ -0,0 +1,12 @@
1
+ /** Tuning of Arc's EmptyState, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** Size, in pixels, of the default folder icon. */
3
+ export const EMPTY_STATE_ICON_SIZE_PX = 24;
4
+ /** Stroke width of the default folder icon. */
5
+ export const EMPTY_STATE_ICON_STROKE_WIDTH = 1.5;
6
+ /** Scale an incoming icon pops from. */
7
+ export const EMPTY_STATE_ICON_ENTER_SCALE = .6;
8
+ /**
9
+ * Window, in milliseconds, after new copy arrives in which a height change springs; later resizes (fonts, container
10
+ * width) follow instantly.
11
+ */
12
+ export const EMPTY_STATE_HEIGHT_MORPH_WINDOW_MS = 120;
@@ -0,0 +1,12 @@
1
+ /** Defaults and tuning of Arc's MetricCard, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** Locale that formats the number when none is passed. */
3
+ export declare const METRIC_CARD_DEFAULT_LOCALE = "es-AR";
4
+ /** Share of the number, from 0 to 1, that must be visible before its digits roll up from zero. */
5
+ export declare const METRIC_CARD_REVEAL_AMOUNT = 0.6;
6
+ /** Scale the change chip grows from and shrinks back to. */
7
+ export declare const METRIC_CARD_CHANGE_ENTER_SCALE = 0.96;
8
+ /** Signs that mark a change as a rise or a fall, read from the start of the `change` copy. */
9
+ export declare const METRIC_CARD_TREND_PATTERN: {
10
+ readonly up: RegExp;
11
+ readonly down: RegExp;
12
+ };
@@ -0,0 +1,12 @@
1
+ /** Defaults and tuning of Arc's MetricCard, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** Locale that formats the number when none is passed. */
3
+ export const METRIC_CARD_DEFAULT_LOCALE = "es-AR";
4
+ /** Share of the number, from 0 to 1, that must be visible before its digits roll up from zero. */
5
+ export const METRIC_CARD_REVEAL_AMOUNT = .6;
6
+ /** Scale the change chip grows from and shrinks back to. */
7
+ export const METRIC_CARD_CHANGE_ENTER_SCALE = .96;
8
+ /** Signs that mark a change as a rise or a fall, read from the start of the `change` copy. */
9
+ export const METRIC_CARD_TREND_PATTERN = {
10
+ up: /^\+/,
11
+ down: /^[-−]/
12
+ };
@@ -0,0 +1,52 @@
1
+ /** Copy and tuning of Arc's Stepper, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** Layout direction of a stepper. */
3
+ export type StepperOrientation = "horizontal" | "vertical";
4
+ /** State of one step: done, in progress, not reached yet, or failed. */
5
+ export type StepperStatus = "complete" | "current" | "upcoming" | "error";
6
+ /** Which descriptions show: every step's, or only the active step's. Errors always show. */
7
+ export type StepperDetails = "all" | "current";
8
+ /**
9
+ * Screen-reader copy of a `Stepper`. The Spanish defaults can be replaced one by one through the `messages` prop; the
10
+ * accessible name and the completion copy keep their own props, `label` and `completeLabel`.
11
+ */
12
+ export type StepperMessages = {
13
+ /** Appended to a completed step's label. */
14
+ completed: string;
15
+ /** Appended to a step not reached yet. */
16
+ notStarted: string;
17
+ /** Appended to a failed step. */
18
+ error: string;
19
+ /** Announced when the current step changes. */
20
+ stepAnnouncement: (values: {
21
+ position: number;
22
+ count: number;
23
+ label: string;
24
+ }) => string;
25
+ };
26
+ /** Spanish screen-reader copy of the stepper. */
27
+ export declare const STEPPER_DEFAULT_MESSAGES: {
28
+ readonly completed: "Completado";
29
+ readonly notStarted: "Sin empezar";
30
+ readonly error: "Error";
31
+ readonly stepAnnouncement: ({ position, count, label }: {
32
+ position: number;
33
+ count: number;
34
+ label: string;
35
+ }) => string;
36
+ };
37
+ /** Accessible name of the stepper when none is passed. */
38
+ export declare const STEPPER_DEFAULT_LABEL = "Progreso";
39
+ /** Copy announced, and shown in the compact caption, once every step is complete, when none is passed. */
40
+ export declare const STEPPER_DEFAULT_COMPLETE_LABEL = "Todos los pasos completados";
41
+ /** Delay, in seconds, before the ring grows around the new current step, after its connector fills. */
42
+ export declare const STEPPER_RING_DELAY_S = 0.12;
43
+ /** Extra delay, in seconds, between a glyph popping in and its stroke starting to draw. */
44
+ export declare const STEPPER_GLYPH_DRAW_DELAY_S = 0.04;
45
+ /** Extra delay, in seconds, before the dot of the alert glyph pops in. */
46
+ export declare const STEPPER_ALERT_DOT_DELAY_S = 0.16;
47
+ /** Scale a glyph pops from and shrinks back to. */
48
+ export declare const STEPPER_GLYPH_ENTER_SCALE = 0.5;
49
+ /** Scale the current step's ring grows from. */
50
+ export declare const STEPPER_RING_ENTER_SCALE = 0.6;
51
+ /** Window, in milliseconds, after new copy arrives in which its slot springs to the new height. */
52
+ export declare const STEPPER_TEXT_MORPH_WINDOW_MS = 700;
@@ -0,0 +1,23 @@
1
+ /** Spanish screen-reader copy of the stepper. */
2
+ export const STEPPER_DEFAULT_MESSAGES = {
3
+ completed: "Completado",
4
+ notStarted: "Sin empezar",
5
+ error: "Error",
6
+ stepAnnouncement: ({ position, count, label }) => `Paso ${position} de ${count}: ${label}`
7
+ };
8
+ /** Accessible name of the stepper when none is passed. */
9
+ export const STEPPER_DEFAULT_LABEL = "Progreso";
10
+ /** Copy announced, and shown in the compact caption, once every step is complete, when none is passed. */
11
+ export const STEPPER_DEFAULT_COMPLETE_LABEL = "Todos los pasos completados";
12
+ /** Delay, in seconds, before the ring grows around the new current step, after its connector fills. */
13
+ export const STEPPER_RING_DELAY_S = .12;
14
+ /** Extra delay, in seconds, between a glyph popping in and its stroke starting to draw. */
15
+ export const STEPPER_GLYPH_DRAW_DELAY_S = .04;
16
+ /** Extra delay, in seconds, before the dot of the alert glyph pops in. */
17
+ export const STEPPER_ALERT_DOT_DELAY_S = .16;
18
+ /** Scale a glyph pops from and shrinks back to. */
19
+ export const STEPPER_GLYPH_ENTER_SCALE = .5;
20
+ /** Scale the current step's ring grows from. */
21
+ export const STEPPER_RING_ENTER_SCALE = .6;
22
+ /** Window, in milliseconds, after new copy arrives in which its slot springs to the new height. */
23
+ export const STEPPER_TEXT_MORPH_WINDOW_MS = 700;
@@ -0,0 +1,62 @@
1
+ /** Copy and tuning of Arc's Timeline, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** Status of a system event. Say the outcome in the title too, so it never rests on colour. */
3
+ export type TimelineTone = "neutral" | "success" | "danger";
4
+ /** Heading levels the day labels can take; Arc uses level 3. */
5
+ export type TimelineHeadingLevel = 2 | 3 | 4 | 5 | 6;
6
+ /**
7
+ * Every visible and announced string of a `Timeline`. The Spanish defaults can be replaced one by one through the
8
+ * `messages` prop.
9
+ */
10
+ export type TimelineMessages = {
11
+ /** Day label of the reference day. */
12
+ today: string;
13
+ /** Day label of the day before the reference day. */
14
+ yesterday: string;
15
+ /** Noun after a day's update count: "1 actualización", "3 actualizaciones". */
16
+ updates: (count: number) => string;
17
+ /** Short time of an event less than a minute old. */
18
+ justNowShort: string;
19
+ /** Spoken time of an event less than a minute old. */
20
+ justNowLong: string;
21
+ /** Short time of an event minutes old: "5 min". */
22
+ minutesShort: (minutes: number) => string;
23
+ /** Spoken time of an event minutes old: "hace 5 minutos". */
24
+ minutesLong: (minutes: number) => string;
25
+ /** Short time of an event hours old: "3 h". */
26
+ hoursShort: (hours: number) => string;
27
+ /** Spoken time of an event hours old: "hace 3 horas". */
28
+ hoursLong: (hours: number) => string;
29
+ /** Announcement of updates that arrive after the first render, with their actors and titles joined. */
30
+ newUpdates: (summary: string) => string;
31
+ };
32
+ /** Spanish copy of the timeline. */
33
+ export declare const TIMELINE_DEFAULT_MESSAGES: {
34
+ readonly today: "Hoy";
35
+ readonly yesterday: "Ayer";
36
+ readonly updates: (count: number) => "actualizaciones" | "actualización";
37
+ readonly justNowShort: "Ahora";
38
+ readonly justNowLong: "recién";
39
+ readonly minutesShort: (minutes: number) => string;
40
+ readonly minutesLong: (minutes: number) => string;
41
+ readonly hoursShort: (hours: number) => string;
42
+ readonly hoursLong: (hours: number) => string;
43
+ readonly newUpdates: (summary: string) => string;
44
+ };
45
+ /** Locale of day labels and clock times when none is passed. */
46
+ export declare const TIMELINE_DEFAULT_LOCALE = "es-AR";
47
+ /** Time zone of day groups and clock times when none is passed; fixed so server and client agree. */
48
+ export declare const TIMELINE_DEFAULT_TIME_ZONE = "UTC";
49
+ /** Heading level of the day labels when none is passed. */
50
+ export declare const TIMELINE_DEFAULT_HEADING_LEVEL = 3;
51
+ /** Today's events younger than this many hours show a relative time instead of a clock time. */
52
+ export declare const TIMELINE_RELATIVE_WINDOW_HOURS = 12;
53
+ /** Seconds between rows revealed together, so the line reads as drawing downward. */
54
+ export declare const TIMELINE_REVEAL_STEP_S = 0.09;
55
+ /** Longest wait, in seconds, a row can be queued behind others before it reveals. */
56
+ export declare const TIMELINE_REVEAL_QUEUE_LIMIT_S = 0.45;
57
+ /** Extra delay, in seconds, before a row that arrived after the first render reveals its marker. */
58
+ export declare const TIMELINE_FRESH_ROW_DELAY_S = 0.12;
59
+ /** Share of a row, from 0 to 1, that must be visible before it reveals. */
60
+ export declare const TIMELINE_REVEAL_AMOUNT = 0.2;
61
+ /** Size, in pixels, of an event's avatar. */
62
+ export declare const TIMELINE_AVATAR_SIZE_PX = 28;
@@ -0,0 +1,31 @@
1
+ /** Spanish copy of the timeline. */
2
+ export const TIMELINE_DEFAULT_MESSAGES = {
3
+ today: "Hoy",
4
+ yesterday: "Ayer",
5
+ updates: (count) => count === 1 ? "actualización" : "actualizaciones",
6
+ justNowShort: "Ahora",
7
+ justNowLong: "recién",
8
+ minutesShort: (minutes) => `${minutes} min`,
9
+ minutesLong: (minutes) => `hace ${minutes} ${minutes === 1 ? "minuto" : "minutos"}`,
10
+ hoursShort: (hours) => `${hours} h`,
11
+ hoursLong: (hours) => `hace ${hours} ${hours === 1 ? "hora" : "horas"}`,
12
+ newUpdates: (summary) => `Nueva actualización: ${summary}`
13
+ };
14
+ /** Locale of day labels and clock times when none is passed. */
15
+ export const TIMELINE_DEFAULT_LOCALE = "es-AR";
16
+ /** Time zone of day groups and clock times when none is passed; fixed so server and client agree. */
17
+ export const TIMELINE_DEFAULT_TIME_ZONE = "UTC";
18
+ /** Heading level of the day labels when none is passed. */
19
+ export const TIMELINE_DEFAULT_HEADING_LEVEL = 3;
20
+ /** Today's events younger than this many hours show a relative time instead of a clock time. */
21
+ export const TIMELINE_RELATIVE_WINDOW_HOURS = 12;
22
+ /** Seconds between rows revealed together, so the line reads as drawing downward. */
23
+ export const TIMELINE_REVEAL_STEP_S = .09;
24
+ /** Longest wait, in seconds, a row can be queued behind others before it reveals. */
25
+ export const TIMELINE_REVEAL_QUEUE_LIMIT_S = .45;
26
+ /** Extra delay, in seconds, before a row that arrived after the first render reveals its marker. */
27
+ export const TIMELINE_FRESH_ROW_DELAY_S = .12;
28
+ /** Share of a row, from 0 to 1, that must be visible before it reveals. */
29
+ export const TIMELINE_REVEAL_AMOUNT = .2;
30
+ /** Size, in pixels, of an event's avatar. */
31
+ export const TIMELINE_AVATAR_SIZE_PX = 28;
@@ -0,0 +1,100 @@
1
+ /** Copy and tuning of Arc's UsageMeter, adapted from Arc (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). */
2
+ /** How full the allowance is: under the warning share, close to the limit, or past it. */
3
+ export type UsageMeterStatus = "ok" | "near" | "over";
4
+ /** Values the meter's copy is built from. Amounts arrive already formatted with their unit, such as "8,4 GB". */
5
+ export type UsageMeterCopyValues = {
6
+ /** What is measured, from `label`. */
7
+ label: string;
8
+ /** The `unit` prop, possibly empty. */
9
+ unit: string;
10
+ /** Formatted plan limit with its unit. */
11
+ limit: string;
12
+ /** Formatted total used with its unit. */
13
+ total: string;
14
+ /** Formatted space left with its unit. */
15
+ free: string;
16
+ /** Formatted overage with its unit. */
17
+ over: string;
18
+ };
19
+ /**
20
+ * Every visible and announced string of a `UsageMeter`. The Spanish defaults can be replaced one by one through the
21
+ * `messages` prop. The legend labels of the remaining space keep their own props, `freeLabel` and `overLabel`.
22
+ */
23
+ export type UsageMeterMessages = {
24
+ /** Caption beside the total, after the rolling number: "GB de 50 GB usados". */
25
+ usedCaption: (values: UsageMeterCopyValues) => string;
26
+ /** Caption while the remaining space is highlighted: "GB libres". */
27
+ freeCaption: (values: UsageMeterCopyValues) => string;
28
+ /** Caption while the overage is highlighted: "GB por encima del límite". */
29
+ overCaption: (values: UsageMeterCopyValues) => string;
30
+ /** Caption while a category is highlighted, with its share of the plan in percent. */
31
+ segmentCaption: (values: UsageMeterCopyValues & {
32
+ segment: string;
33
+ share: number;
34
+ }) => string;
35
+ /** Status badge under the warning share. */
36
+ freeBadge: (values: UsageMeterCopyValues) => string;
37
+ /** Status badge close to the limit. */
38
+ nearBadge: (values: UsageMeterCopyValues) => string;
39
+ /** Status badge past the limit. */
40
+ overBadge: (values: UsageMeterCopyValues) => string;
41
+ /** Screen-reader copy of the total. */
42
+ usedSummary: (values: UsageMeterCopyValues) => string;
43
+ /** Text alternative of the bar: the total, every category and the status. */
44
+ barSummary: (values: UsageMeterCopyValues & {
45
+ status: UsageMeterStatus;
46
+ segments: string;
47
+ }) => string;
48
+ /** Accessible name of the legend. */
49
+ legendLabel: (values: UsageMeterCopyValues) => string;
50
+ /** Announcement when usage drops back under the warning share. */
51
+ okAnnouncement: (values: UsageMeterCopyValues) => string;
52
+ /** Announcement when usage gets close to the limit. */
53
+ nearAnnouncement: (values: UsageMeterCopyValues) => string;
54
+ /** Announcement when usage passes the limit or the overage grows. */
55
+ overAnnouncement: (values: UsageMeterCopyValues) => string;
56
+ };
57
+ /** Spanish copy of the meter. */
58
+ export declare const USAGE_METER_DEFAULT_MESSAGES: {
59
+ readonly usedCaption: ({ unit, limit }: UsageMeterCopyValues) => string;
60
+ readonly freeCaption: ({ unit }: UsageMeterCopyValues) => string;
61
+ readonly overCaption: ({ unit }: UsageMeterCopyValues) => string;
62
+ readonly segmentCaption: ({ unit, segment, share }: UsageMeterCopyValues & {
63
+ segment: string;
64
+ share: number;
65
+ }) => string;
66
+ readonly freeBadge: ({ free }: UsageMeterCopyValues) => string;
67
+ readonly nearBadge: () => string;
68
+ readonly overBadge: ({ over }: UsageMeterCopyValues) => string;
69
+ readonly usedSummary: ({ total, limit }: UsageMeterCopyValues) => string;
70
+ readonly barSummary: ({ label, total, limit, segments, status, free, over }: UsageMeterCopyValues & {
71
+ status: UsageMeterStatus;
72
+ segments: string;
73
+ }) => string;
74
+ readonly legendLabel: ({ label }: UsageMeterCopyValues) => string;
75
+ readonly okAnnouncement: ({ free }: UsageMeterCopyValues) => string;
76
+ readonly nearAnnouncement: ({ free }: UsageMeterCopyValues) => string;
77
+ readonly overAnnouncement: ({ over }: UsageMeterCopyValues) => string;
78
+ };
79
+ /** Legend label of the remaining space when none is passed. */
80
+ export declare const USAGE_METER_DEFAULT_FREE_LABEL = "Libre";
81
+ /** Legend label of the overage when none is passed. */
82
+ export declare const USAGE_METER_DEFAULT_OVER_LABEL = "Excedente";
83
+ /** Locale that formats the amounts when none is passed. */
84
+ export declare const USAGE_METER_DEFAULT_LOCALE = "es-AR";
85
+ /** Digits after the decimal separator when none is passed. */
86
+ export declare const USAGE_METER_DEFAULT_DECIMALS = 1;
87
+ /** Share of the limit at which the badge warns that it is almost full, when none is passed. */
88
+ export declare const USAGE_METER_DEFAULT_WARN_AT = 0.9;
89
+ /** Share of the meter, from 0 to 1, that must be visible before its segments grow in. */
90
+ export declare const USAGE_METER_REVEAL_AMOUNT = 0.4;
91
+ /** Delay, in seconds, between segments growing in one after another on first view. */
92
+ export declare const USAGE_METER_REVEAL_STAGGER_S = 0.07;
93
+ /** Gap, in pixels, a segment stops short of the next one, so neighbours read apart without an outline. */
94
+ export declare const USAGE_METER_SEGMENT_GAP_PX = 2;
95
+ /** Category colours are steps of the accent, strongest first; up to this many read clearly. */
96
+ export declare const USAGE_METER_SEGMENT_COLOR_COUNT = 4;
97
+ /** Legend key of the remaining space, or of the overage once usage passes the limit. Segment keys carry a prefix, so no segment id can collide with it. */
98
+ export declare const USAGE_METER_FREE_ID = "free";
99
+ /** Prefix of every segment's legend key, which keeps segment ids apart from the remaining-space item. */
100
+ export declare const USAGE_METER_SEGMENT_KEY_PREFIX = "segment:";
@@ -0,0 +1,38 @@
1
+ /** Spanish copy of the meter. */
2
+ export const USAGE_METER_DEFAULT_MESSAGES = {
3
+ usedCaption: ({ unit, limit }) => `${unit} de ${limit} usados`.trim(),
4
+ freeCaption: ({ unit }) => `${unit} libres`.trim(),
5
+ overCaption: ({ unit }) => `${unit} por encima del límite`.trim(),
6
+ segmentCaption: ({ unit, segment, share }) => `${unit} en ${segment} · ${share} % del plan`.trim(),
7
+ freeBadge: ({ free }) => `${free} libres`,
8
+ nearBadge: () => "Casi lleno",
9
+ overBadge: ({ over }) => `${over} de más`,
10
+ usedSummary: ({ total, limit }) => `${total} de ${limit} usados`,
11
+ barSummary: ({ label, total, limit, segments, status, free, over }) => `${label}: ${total} de ${limit} usados. ${segments}. ${status === "over" ? `Supera el límite por ${over}.` : `${free} libres${status === "near" ? ", casi lleno" : ""}.`}`,
12
+ legendLabel: ({ label }) => `${label} por categoría`,
13
+ okAnnouncement: ({ free }) => `Por debajo del límite. ${free} libres.`,
14
+ nearAnnouncement: ({ free }) => `Casi lleno. ${free} libres.`,
15
+ overAnnouncement: ({ over }) => `Supera el límite del plan por ${over}.`
16
+ };
17
+ /** Legend label of the remaining space when none is passed. */
18
+ export const USAGE_METER_DEFAULT_FREE_LABEL = "Libre";
19
+ /** Legend label of the overage when none is passed. */
20
+ export const USAGE_METER_DEFAULT_OVER_LABEL = "Excedente";
21
+ /** Locale that formats the amounts when none is passed. */
22
+ export const USAGE_METER_DEFAULT_LOCALE = "es-AR";
23
+ /** Digits after the decimal separator when none is passed. */
24
+ export const USAGE_METER_DEFAULT_DECIMALS = 1;
25
+ /** Share of the limit at which the badge warns that it is almost full, when none is passed. */
26
+ export const USAGE_METER_DEFAULT_WARN_AT = .9;
27
+ /** Share of the meter, from 0 to 1, that must be visible before its segments grow in. */
28
+ export const USAGE_METER_REVEAL_AMOUNT = .4;
29
+ /** Delay, in seconds, between segments growing in one after another on first view. */
30
+ export const USAGE_METER_REVEAL_STAGGER_S = .07;
31
+ /** Gap, in pixels, a segment stops short of the next one, so neighbours read apart without an outline. */
32
+ export const USAGE_METER_SEGMENT_GAP_PX = 2;
33
+ /** Category colours are steps of the accent, strongest first; up to this many read clearly. */
34
+ export const USAGE_METER_SEGMENT_COLOR_COUNT = 4;
35
+ /** Legend key of the remaining space, or of the overage once usage passes the limit. Segment keys carry a prefix, so no segment id can collide with it. */
36
+ export const USAGE_METER_FREE_ID = "free";
37
+ /** Prefix of every segment's legend key, which keeps segment ids apart from the remaining-space item. */
38
+ export const USAGE_METER_SEGMENT_KEY_PREFIX = "segment:";
@@ -0,0 +1,9 @@
1
+ import type { RefObject } from "react";
2
+ /**
3
+ * Reports whether the element has been at least `amount` visible at some point. Without `IntersectionObserver` (old
4
+ * engines) it reports `true` after mounting, so content never stays in its pre-entrance state.
5
+ * @param ref - Element to watch.
6
+ * @param amount - Share of the element, from 0 to 1, that must be visible.
7
+ * @returns `false` until the element first enters the viewport, then `true` for good.
8
+ */
9
+ export declare function useHasEnteredView(ref: RefObject<Element | null>, amount: number): boolean;
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { c as _c } from "react/compiler-runtime";
3
+ /** Tells once whether an element has scrolled into view, for entrances that wait until people can see them. */
4
+ import { useEffect, useState } from "react";
5
+ import { inView } from "motion/react";
6
+ /**
7
+ * Reports whether the element has been at least `amount` visible at some point. Without `IntersectionObserver` (old
8
+ * engines) it reports `true` after mounting, so content never stays in its pre-entrance state.
9
+ * @param ref - Element to watch.
10
+ * @param amount - Share of the element, from 0 to 1, that must be visible.
11
+ * @returns `false` until the element first enters the viewport, then `true` for good.
12
+ */
13
+ export function useHasEnteredView(ref, amount) {
14
+ const $ = _c(5);
15
+ const [hasEntered, setHasEntered] = useState(false);
16
+ let t0;
17
+ let t1;
18
+ if ($[0] !== amount || $[1] !== hasEntered || $[2] !== ref) {
19
+ t0 = () => {
20
+ const element = ref.current;
21
+ if (hasEntered || !element) {
22
+ return;
23
+ }
24
+ if (typeof IntersectionObserver === "undefined") {
25
+ setHasEntered(true);
26
+ return;
27
+ }
28
+ return inView(element, () => setHasEntered(true), { amount });
29
+ };
30
+ t1 = [
31
+ amount,
32
+ hasEntered,
33
+ ref
34
+ ];
35
+ $[0] = amount;
36
+ $[1] = hasEntered;
37
+ $[2] = ref;
38
+ $[3] = t0;
39
+ $[4] = t1;
40
+ } else {
41
+ t0 = $[3];
42
+ t1 = $[4];
43
+ }
44
+ useEffect(t0, t1);
45
+ return hasEntered;
46
+ }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,8 @@ export * from "./components/action-button.js";
7
7
  export * from "./components/avatar.js";
8
8
  export * from "./components/badge.js";
9
9
  export * from "./components/button.js";
10
+ export { buttonClassName, type ButtonClassNameOptions } from "./components/button-recipe.js";
11
+ export * from "./components/button-link.js";
10
12
  export * from "./components/card.js";
11
13
  export * from "./components/carousel.js";
12
14
  export * from "./components/checkbox.js";
@@ -53,6 +55,11 @@ export * from "./components/animated-count.js";
53
55
  export * from "./components/animated-list-item.js";
54
56
  export * from "./components/presence-swap.js";
55
57
  export * from "./components/progress-ring.js";
58
+ export * from "./components/empty-state.js";
59
+ export * from "./components/metric-card.js";
60
+ export * from "./components/stepper.js";
61
+ export * from "./components/timeline.js";
62
+ export * from "./components/usage-meter.js";
56
63
  export * from "./components/account-menu.js";
57
64
  export * from "./components/rich-text-content.js";
58
65
  export * from "./components/rich-markdown-content.js";
package/dist/index.js CHANGED
@@ -6,6 +6,9 @@ export * from "./components/action-button.js";
6
6
  export * from "./components/avatar.js";
7
7
  export * from "./components/badge.js";
8
8
  export * from "./components/button.js";
9
+ // From the recipe module, which has no client directive, so it also runs in Server Components.
10
+ export { buttonClassName } from "./components/button-recipe.js";
11
+ export * from "./components/button-link.js";
9
12
  export * from "./components/card.js";
10
13
  export * from "./components/carousel.js";
11
14
  export * from "./components/checkbox.js";
@@ -52,6 +55,11 @@ export * from "./components/animated-count.js";
52
55
  export * from "./components/animated-list-item.js";
53
56
  export * from "./components/presence-swap.js";
54
57
  export * from "./components/progress-ring.js";
58
+ export * from "./components/empty-state.js";
59
+ export * from "./components/metric-card.js";
60
+ export * from "./components/stepper.js";
61
+ export * from "./components/timeline.js";
62
+ export * from "./components/usage-meter.js";
55
63
  export * from "./components/account-menu.js";
56
64
  export * from "./components/rich-text-content.js";
57
65
  export * from "./components/rich-markdown-content.js";
@@ -0,0 +1,53 @@
1
+ /** A spring written as visual duration and bounce. */
2
+ type VisualSpring = {
3
+ visualDuration: number;
4
+ bounce: number;
5
+ };
6
+ /**
7
+ * Motion drops inherited velocity on time-defined springs, so values that retarget mid-flight run the same springs
8
+ * written as stiffness and damping.
9
+ * @param spring - Visual duration and bounce of the spring.
10
+ * @param restDelta - Distance at which the spring counts as settled.
11
+ * @returns The equivalent physical spring.
12
+ */
13
+ export declare function toPhysicalSpring({ visualDuration, bounce }: VisualSpring, restDelta?: number): {
14
+ type: "spring";
15
+ stiffness: number;
16
+ damping: number;
17
+ restDelta: number;
18
+ restSpeed: number;
19
+ };
20
+ /**
21
+ * Starts an animation on the next frame, so the render that caused it never swallows a spring's first frames.
22
+ * @param start - Starts the animation and returns its controls.
23
+ * @returns A cleanup that cancels the pending start or stops the running animation.
24
+ */
25
+ export declare function startNextFrame(start: () => {
26
+ stop: () => void;
27
+ }): () => void;
28
+ /**
29
+ * Formats a number the way the odometer draws it, for the screen-reader copy beside it.
30
+ * @param value - Number to format.
31
+ * @param decimals - Digits after the decimal separator.
32
+ * @param locale - Formatting locale.
33
+ * @returns The formatted number.
34
+ */
35
+ export declare function formatOdometerValue(value: number, decimals: number, locale: string): string;
36
+ export type ArcOdometerProps = {
37
+ value: number;
38
+ /** Digits after the decimal separator. */
39
+ decimals?: number;
40
+ /** Formatting locale of separators and grouping. */
41
+ locale: string;
42
+ /** Holds every wheel at zero; once it turns false the digits roll up from zero, one column after another. */
43
+ armed?: boolean;
44
+ reduceMotion: boolean;
45
+ className?: string;
46
+ };
47
+ /**
48
+ * A number that rolls to each new value, digit by digit, in the direction it moved.
49
+ * @param props - Value, decimals, locale, reveal state and motion preference.
50
+ * @returns The odometer, hidden from assistive technology.
51
+ */
52
+ export declare function ArcOdometer({ value, decimals, locale, armed, reduceMotion, className }: ArcOdometerProps): import("react").JSX.Element;
53
+ export {};