@astryxdesign/cli 0.7.12-canary.9a690d5 → 0.7.12-canary.f543ec7
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/api/component/__fixtures__/resolutions/modules.txt +2 -2
- package/assets/templates/blocks/components/Calendar/useCalendarConstraintsHookUsage.doc.mjs +14 -0
- package/assets/templates/blocks/components/Calendar/useCalendarConstraintsHookUsage.tsx +146 -0
- package/assets/templates/blocks/components/Calendar/useCalendarNavigationHookUsage.doc.mjs +14 -0
- package/assets/templates/blocks/components/Calendar/useCalendarNavigationHookUsage.tsx +173 -0
- package/assets/templates/themes/butter/butterTheme.ts +1 -1
- package/assets/templates/themes/stone/stoneTheme.ts +1 -1
- package/assets/templates/themes/y2k/y2kTheme.ts +1 -1
- package/package.json +6 -6
|
@@ -247,9 +247,9 @@ useAutoMediaMode useAutoMediaMode hooks/useAnimatedLayout.doc.mjs hooks/useAutoM
|
|
|
247
247
|
useBackdropPress useBackdropPress Layer/Layer.doc.mjs Layer/useBackdropPress.ts
|
|
248
248
|
useBaseTablePlugins useBaseTablePlugins Table/Table.doc.mjs Table/useBaseTablePlugins.ts
|
|
249
249
|
useBusyAnnouncement useBusyAnnouncement hooks/useAnimatedLayout.doc.mjs hooks/useBusyAnnouncement.ts
|
|
250
|
-
useCalendarConstraints useCalendarConstraints Calendar/
|
|
250
|
+
useCalendarConstraints useCalendarConstraints Calendar/useCalendarConstraints.doc.mjs Calendar/hooks/useCalendarConstraints.ts
|
|
251
251
|
useCalendarDays useCalendarDays Calendar/useCalendarDays.doc.mjs Calendar/hooks/useCalendarDays.ts
|
|
252
|
-
useCalendarNavigation useCalendarNavigation Calendar/
|
|
252
|
+
useCalendarNavigation useCalendarNavigation Calendar/useCalendarNavigation.doc.mjs Calendar/hooks/useCalendarNavigation.ts
|
|
253
253
|
useChatComposerTokens useChatComposerTokens Chat/Chat.doc.mjs Chat/useChatComposerTokens.ts
|
|
254
254
|
useChatDictation useChatDictation Chat/Chat.doc.mjs Chat/useChatDictation.ts
|
|
255
255
|
useChatNewMessages useChatNewMessages Chat/Chat.doc.mjs Chat/useChatNewMessages.ts
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'useCalendarConstraints',
|
|
7
|
+
name: 'useCalendarConstraints — Hotel Booking Range',
|
|
8
|
+
displayName: 'useCalendarConstraints — Hotel Booking Range',
|
|
9
|
+
description:
|
|
10
|
+
'A hotel booking range picker enforcing season min/max dates, a 7-night maximum stay once check-in is picked, and a custom rule disabling closed Mondays.',
|
|
11
|
+
isReady: true,
|
|
12
|
+
aspectRatio: 4 / 3,
|
|
13
|
+
componentsUsed: ['Button', 'Layout', 'Text'],
|
|
14
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
6
|
+
import {
|
|
7
|
+
useCalendarConstraints,
|
|
8
|
+
useCalendarDays,
|
|
9
|
+
type CalendarDay,
|
|
10
|
+
} from '@astryxdesign/core/Calendar';
|
|
11
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
12
|
+
import {HStack, VStack} from '@astryxdesign/core/Layout';
|
|
13
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
14
|
+
|
|
15
|
+
// Hotel closed on Mondays (day === 1)
|
|
16
|
+
const isNotMonday = (date: Date) => date.getDay() !== 1;
|
|
17
|
+
|
|
18
|
+
export default function UseCalendarConstraintsHookUsage() {
|
|
19
|
+
const [checkIn, setCheckIn] = useState<CalendarDay['date'] | null>(null);
|
|
20
|
+
const [checkOut, setCheckOut] = useState<CalendarDay['date'] | null>(null);
|
|
21
|
+
|
|
22
|
+
// June 2026 season: open Jun 5 – Jun 25, max 7 nights (8-day span), closed Mondays.
|
|
23
|
+
// When checkOut is already chosen, clear rangeAnchor so full season remains viewable without lingering span restrictions.
|
|
24
|
+
const {isDateDisabled} = useCalendarConstraints({
|
|
25
|
+
min: '2026-06-05',
|
|
26
|
+
max: '2026-06-25',
|
|
27
|
+
maxRangeSpan: 8,
|
|
28
|
+
rangeAnchor: checkOut ? null : checkIn,
|
|
29
|
+
dateConstraints: [isNotMonday],
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const {weeks, dayNames} = useCalendarDays({
|
|
33
|
+
year: 2026,
|
|
34
|
+
month: 6,
|
|
35
|
+
weekStartsOn: 0,
|
|
36
|
+
hasVariableRowCount: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const handleSelect = (day: CalendarDay) => {
|
|
40
|
+
if (day.isOutside || isDateDisabled(day.date)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// If no check-in yet, or already booked, or clicking on/before current check-in: start new check-in
|
|
44
|
+
if (!checkIn || checkOut || day.date.day <= checkIn.day) {
|
|
45
|
+
setCheckIn(day.date);
|
|
46
|
+
setCheckOut(null);
|
|
47
|
+
} else {
|
|
48
|
+
// Pick is after checkIn: set as check-out
|
|
49
|
+
setCheckOut(day.date);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const handleReset = () => {
|
|
54
|
+
setCheckIn(null);
|
|
55
|
+
setCheckOut(null);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<VStack gap={3}>
|
|
60
|
+
<VStack gap={1}>
|
|
61
|
+
<Text type="body" weight="bold">
|
|
62
|
+
Hotel Booking — June 2026
|
|
63
|
+
</Text>
|
|
64
|
+
<Text type="supporting" color="secondary">
|
|
65
|
+
Season: Jun 5 – Jun 25 · Max stay: 7 nights · Closed Mondays
|
|
66
|
+
</Text>
|
|
67
|
+
</VStack>
|
|
68
|
+
<HStack gap={2} vAlign="center">
|
|
69
|
+
<Text type="supporting">
|
|
70
|
+
{checkIn
|
|
71
|
+
? checkOut
|
|
72
|
+
? `Booked: Jun ${checkIn.day} – Jun ${checkOut.day}`
|
|
73
|
+
: `Check-in: Jun ${checkIn.day} (pick check-out)`
|
|
74
|
+
: 'Pick a check-in date'}
|
|
75
|
+
</Text>
|
|
76
|
+
{checkIn && (
|
|
77
|
+
<Button
|
|
78
|
+
label="Reset"
|
|
79
|
+
size="sm"
|
|
80
|
+
variant="secondary"
|
|
81
|
+
onClick={handleReset}
|
|
82
|
+
/>
|
|
83
|
+
)}
|
|
84
|
+
</HStack>
|
|
85
|
+
<table style={{tableLayout: 'fixed', width: 280}}>
|
|
86
|
+
<thead>
|
|
87
|
+
<tr>
|
|
88
|
+
{dayNames.map((name, i) => (
|
|
89
|
+
<th key={i} scope="col">
|
|
90
|
+
<Text type="supporting" color="secondary">
|
|
91
|
+
{name}
|
|
92
|
+
</Text>
|
|
93
|
+
</th>
|
|
94
|
+
))}
|
|
95
|
+
</tr>
|
|
96
|
+
</thead>
|
|
97
|
+
<tbody>
|
|
98
|
+
{weeks.map(week => (
|
|
99
|
+
<tr key={week[0].iso}>
|
|
100
|
+
{week.map(day => {
|
|
101
|
+
if (day.isOutside) {
|
|
102
|
+
return <td key={day.iso} align="center" />;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const disabled = isDateDisabled(day.date);
|
|
106
|
+
const isSelected =
|
|
107
|
+
(checkIn &&
|
|
108
|
+
checkIn.day === day.date.day &&
|
|
109
|
+
checkIn.month === day.date.month) ||
|
|
110
|
+
(checkOut &&
|
|
111
|
+
checkOut.day === day.date.day &&
|
|
112
|
+
checkOut.month === day.date.month);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<td key={day.iso} align="center">
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
disabled={disabled}
|
|
119
|
+
onClick={() => handleSelect(day)}
|
|
120
|
+
aria-pressed={isSelected ? 'true' : 'false'}
|
|
121
|
+
aria-label={`June ${day.dayNumber}`}
|
|
122
|
+
style={{
|
|
123
|
+
width: 32,
|
|
124
|
+
height: 32,
|
|
125
|
+
borderRadius: 6,
|
|
126
|
+
border: isSelected ? '1px solid currentColor' : 'none',
|
|
127
|
+
background: 'transparent',
|
|
128
|
+
opacity: disabled ? 0.35 : 1,
|
|
129
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
130
|
+
}}>
|
|
131
|
+
<Text
|
|
132
|
+
type="body"
|
|
133
|
+
color={disabled ? 'secondary' : 'primary'}>
|
|
134
|
+
{day.dayNumber}
|
|
135
|
+
</Text>
|
|
136
|
+
</button>
|
|
137
|
+
</td>
|
|
138
|
+
);
|
|
139
|
+
})}
|
|
140
|
+
</tr>
|
|
141
|
+
))}
|
|
142
|
+
</tbody>
|
|
143
|
+
</table>
|
|
144
|
+
</VStack>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'useCalendarNavigation',
|
|
7
|
+
name: 'useCalendarNavigation — Month Pager',
|
|
8
|
+
displayName: 'useCalendarNavigation — Month Pager',
|
|
9
|
+
description:
|
|
10
|
+
'A calendar month pager with previous/next navigation buttons, localized month-year label, and cross-month arrow key navigation using pendingFocus.',
|
|
11
|
+
isReady: true,
|
|
12
|
+
aspectRatio: 4 / 3,
|
|
13
|
+
componentsUsed: ['Button', 'Layout', 'Text'],
|
|
14
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useEffect, useRef, useState} from 'react';
|
|
6
|
+
import {
|
|
7
|
+
useCalendarDays,
|
|
8
|
+
useCalendarNavigation,
|
|
9
|
+
type CalendarDay,
|
|
10
|
+
type ISODateString,
|
|
11
|
+
} from '@astryxdesign/core/Calendar';
|
|
12
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
13
|
+
import {HStack, VStack} from '@astryxdesign/core/Layout';
|
|
14
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
15
|
+
|
|
16
|
+
export default function UseCalendarNavigationHookUsage() {
|
|
17
|
+
const [focusDate, setFocusDate] = useState<ISODateString>(
|
|
18
|
+
'2026-06-01' as ISODateString,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
monthYearLabel,
|
|
23
|
+
visibleCalendarMonths,
|
|
24
|
+
navigateMonth,
|
|
25
|
+
pendingFocus,
|
|
26
|
+
clearPendingFocus,
|
|
27
|
+
} = useCalendarNavigation({
|
|
28
|
+
focusDate,
|
|
29
|
+
onFocusDateChange: setFocusDate,
|
|
30
|
+
numberOfMonths: 1,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const {weeks, dayNames} = useCalendarDays({
|
|
34
|
+
...visibleCalendarMonths[0],
|
|
35
|
+
weekStartsOn: 0,
|
|
36
|
+
hasVariableRowCount: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const dayButtonRefs = useRef<Map<string, HTMLButtonElement>>(new Map());
|
|
40
|
+
|
|
41
|
+
// Move focus to target date when navigating across month boundaries
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (pendingFocus) {
|
|
44
|
+
const el = dayButtonRefs.current.get(pendingFocus);
|
|
45
|
+
if (el) {
|
|
46
|
+
el.focus();
|
|
47
|
+
clearPendingFocus();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, [pendingFocus, clearPendingFocus, weeks]);
|
|
51
|
+
|
|
52
|
+
// Arrow key navigation moving across days and month boundaries with RTL awareness (DR6, DR11)
|
|
53
|
+
const handleKeyDown = (
|
|
54
|
+
e: React.KeyboardEvent<HTMLButtonElement>,
|
|
55
|
+
day: CalendarDay,
|
|
56
|
+
) => {
|
|
57
|
+
if (day.isOutside) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const isRtl =
|
|
62
|
+
typeof window !== 'undefined' &&
|
|
63
|
+
getComputedStyle(e.currentTarget).direction === 'rtl';
|
|
64
|
+
|
|
65
|
+
const isNext = isRtl ? e.key === 'ArrowLeft' : e.key === 'ArrowRight';
|
|
66
|
+
const isPrev = isRtl ? e.key === 'ArrowRight' : e.key === 'ArrowLeft';
|
|
67
|
+
|
|
68
|
+
if (isNext) {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
const inMonthDays = weeks.flatMap(w => w.filter(d => !d.isOutside));
|
|
71
|
+
const currentIndex = inMonthDays.findIndex(d => d.iso === day.iso);
|
|
72
|
+
if (currentIndex === inMonthDays.length - 1) {
|
|
73
|
+
// Last day of month: advance month and focus next day across boundary
|
|
74
|
+
navigateMonth(1, day.iso, 1);
|
|
75
|
+
} else {
|
|
76
|
+
const nextDay = inMonthDays[currentIndex + 1];
|
|
77
|
+
dayButtonRefs.current.get(nextDay.iso)?.focus();
|
|
78
|
+
}
|
|
79
|
+
} else if (isPrev) {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
const inMonthDays = weeks.flatMap(w => w.filter(d => !d.isOutside));
|
|
82
|
+
const currentIndex = inMonthDays.findIndex(d => d.iso === day.iso);
|
|
83
|
+
if (currentIndex === 0) {
|
|
84
|
+
// First day of month: step back month and focus previous day across boundary
|
|
85
|
+
navigateMonth(-1, day.iso, 1);
|
|
86
|
+
} else {
|
|
87
|
+
const prevDay = inMonthDays[currentIndex - 1];
|
|
88
|
+
dayButtonRefs.current.get(prevDay.iso)?.focus();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<VStack gap={3} style={{width: 280}}>
|
|
95
|
+
<HStack gap={2} vAlign="center" hAlign="between">
|
|
96
|
+
<Button
|
|
97
|
+
label="Previous"
|
|
98
|
+
size="sm"
|
|
99
|
+
variant="secondary"
|
|
100
|
+
onClick={() => navigateMonth(-1)}
|
|
101
|
+
aria-label="Previous month"
|
|
102
|
+
/>
|
|
103
|
+
<Text type="body" weight="bold">
|
|
104
|
+
{monthYearLabel}
|
|
105
|
+
</Text>
|
|
106
|
+
<Button
|
|
107
|
+
label="Next"
|
|
108
|
+
size="sm"
|
|
109
|
+
variant="secondary"
|
|
110
|
+
onClick={() => navigateMonth(1)}
|
|
111
|
+
aria-label="Next month"
|
|
112
|
+
/>
|
|
113
|
+
</HStack>
|
|
114
|
+
|
|
115
|
+
<table style={{tableLayout: 'fixed', width: 280}}>
|
|
116
|
+
<thead>
|
|
117
|
+
<tr>
|
|
118
|
+
{dayNames.map((name, i) => (
|
|
119
|
+
<th key={i} scope="col">
|
|
120
|
+
<Text type="supporting" color="secondary">
|
|
121
|
+
{name}
|
|
122
|
+
</Text>
|
|
123
|
+
</th>
|
|
124
|
+
))}
|
|
125
|
+
</tr>
|
|
126
|
+
</thead>
|
|
127
|
+
<tbody>
|
|
128
|
+
{weeks.map(week => (
|
|
129
|
+
<tr key={week[0].iso}>
|
|
130
|
+
{week.map(day => (
|
|
131
|
+
<td key={day.iso} align="center">
|
|
132
|
+
<button
|
|
133
|
+
type="button"
|
|
134
|
+
ref={el => {
|
|
135
|
+
if (el) {
|
|
136
|
+
dayButtonRefs.current.set(day.iso, el);
|
|
137
|
+
} else {
|
|
138
|
+
dayButtonRefs.current.delete(day.iso);
|
|
139
|
+
}
|
|
140
|
+
}}
|
|
141
|
+
disabled={day.isOutside}
|
|
142
|
+
aria-hidden={day.isOutside || undefined}
|
|
143
|
+
onKeyDown={e => handleKeyDown(e, day)}
|
|
144
|
+
aria-label={
|
|
145
|
+
day.isOutside
|
|
146
|
+
? undefined
|
|
147
|
+
: `${monthYearLabel} ${day.dayNumber}`
|
|
148
|
+
}
|
|
149
|
+
tabIndex={day.isOutside ? -1 : 0}
|
|
150
|
+
style={{
|
|
151
|
+
width: 32,
|
|
152
|
+
height: 32,
|
|
153
|
+
borderRadius: 6,
|
|
154
|
+
border: 'none',
|
|
155
|
+
background: 'transparent',
|
|
156
|
+
opacity: day.isOutside ? 0.35 : 1,
|
|
157
|
+
cursor: day.isOutside ? 'not-allowed' : 'pointer',
|
|
158
|
+
}}>
|
|
159
|
+
<Text
|
|
160
|
+
type="body"
|
|
161
|
+
color={day.isOutside ? 'secondary' : 'primary'}>
|
|
162
|
+
{day.dayNumber}
|
|
163
|
+
</Text>
|
|
164
|
+
</button>
|
|
165
|
+
</td>
|
|
166
|
+
))}
|
|
167
|
+
</tr>
|
|
168
|
+
))}
|
|
169
|
+
</tbody>
|
|
170
|
+
</table>
|
|
171
|
+
</VStack>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
@@ -260,7 +260,7 @@ export const butterTheme = defineTheme({
|
|
|
260
260
|
'--color-tint-hover': [neutral.light[0], neutral.dark[100]],
|
|
261
261
|
|
|
262
262
|
// Typography override
|
|
263
|
-
'--text-supporting-size': '
|
|
263
|
+
'--text-supporting-size': '0.75rem', // 12px at the default root size
|
|
264
264
|
|
|
265
265
|
// Element sizes — slightly taller defaults so the new input padding
|
|
266
266
|
// (--spacing-2 block) has room to breathe.
|
|
@@ -240,7 +240,7 @@ export const stoneTheme = defineTheme({
|
|
|
240
240
|
'--color-tint-hover': [neutral.light[0], neutral.dark[100]],
|
|
241
241
|
|
|
242
242
|
// Typography override
|
|
243
|
-
'--text-supporting-size': '
|
|
243
|
+
'--text-supporting-size': '0.75rem', // 12px at the default root size
|
|
244
244
|
|
|
245
245
|
// Categorical
|
|
246
246
|
// Light mode pairs pastel stop 90 surfaces with stop 30 foregrounds.
|
|
@@ -236,7 +236,7 @@ export const y2kTheme = defineTheme({
|
|
|
236
236
|
'--color-tint-hover': [neutral.light[15], neutral.dark[95]],
|
|
237
237
|
|
|
238
238
|
// Typography override
|
|
239
|
-
'--text-supporting-size': '
|
|
239
|
+
'--text-supporting-size': '0.75rem', // 12px at the default root size
|
|
240
240
|
|
|
241
241
|
// Categorical colors
|
|
242
242
|
'--color-background-green': [green.light[80], green.dark[80]],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.7.12-canary.
|
|
3
|
+
"version": "0.7.12-canary.f543ec7",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"zod": "^4.4.3"
|
|
125
125
|
},
|
|
126
126
|
"peerDependencies": {
|
|
127
|
-
"@astryxdesign/core": "0.7.12-canary.
|
|
127
|
+
"@astryxdesign/core": "0.7.12-canary.f543ec7"
|
|
128
128
|
},
|
|
129
129
|
"peerDependenciesMeta": {
|
|
130
130
|
"@astryxdesign/core": {
|
|
@@ -132,10 +132,10 @@
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
"devDependencies": {
|
|
135
|
-
"@astryxdesign/charts": "0.7.12-canary.
|
|
136
|
-
"@astryxdesign/core": "0.7.12-canary.
|
|
137
|
-
"@astryxdesign/lab": "0.7.12-canary.
|
|
138
|
-
"@astryxdesign/theme-neutral": "0.7.12-canary.
|
|
135
|
+
"@astryxdesign/charts": "0.7.12-canary.f543ec7",
|
|
136
|
+
"@astryxdesign/core": "0.7.12-canary.f543ec7",
|
|
137
|
+
"@astryxdesign/lab": "0.7.12-canary.f543ec7",
|
|
138
|
+
"@astryxdesign/theme-neutral": "0.7.12-canary.f543ec7",
|
|
139
139
|
"@heroicons/react": "^2.2.0",
|
|
140
140
|
"@stylexjs/stylex": "^0.19.0",
|
|
141
141
|
"@types/babel__core": "^7.20.5",
|