@djangocfg/ui-tools 2.1.411 → 2.1.412
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/package.json +6 -6
- package/src/tools/Chat/composer/AttachContext.tsx +22 -0
- package/src/tools/Chat/composer/Composer.tsx +108 -6
- package/src/tools/Chat/composer/ComposerMenuButton.tsx +39 -2
- package/src/tools/Chat/composer/fileToAttachment.ts +53 -0
- package/src/tools/Chat/composer/index.ts +16 -1
- package/src/tools/Chat/composer/types.ts +71 -0
- package/src/tools/Chat/composer/useComposerAttach.tsx +218 -0
- package/src/tools/Chat/hooks/useChat.ts +32 -0
- package/src/tools/Chat/hooks/useChatComposer.ts +13 -0
- package/src/tools/Chat/messages/MessageBubble.tsx +1 -1
- package/src/tools/Chat/public.ts +1 -0
- package/src/tools/Chat/types/events.ts +50 -0
- package/src/tools/Chat/types/index.ts +1 -1
- package/src/tools/Chat/types/message.ts +5 -0
- package/src/tools/CronScheduler/CronScheduler.client.tsx +42 -15
- package/src/tools/CronScheduler/components/CustomInput.tsx +26 -7
- package/src/tools/CronScheduler/components/DayChips.tsx +20 -7
- package/src/tools/CronScheduler/components/MonthDayGrid.tsx +35 -10
- package/src/tools/CronScheduler/components/SchedulePreview.tsx +8 -5
- package/src/tools/CronScheduler/components/ScheduleTypeSelector.tsx +12 -3
- package/src/tools/CronScheduler/components/TimeSelector.tsx +36 -13
- package/src/tools/CronScheduler/context/CronSchedulerContext.tsx +4 -0
- package/src/tools/CronScheduler/context/hooks.ts +8 -0
- package/src/tools/CronScheduler/context/index.ts +1 -0
- package/src/tools/CronScheduler/index.tsx +2 -0
- package/src/tools/CronScheduler/lazy.tsx +1 -0
- package/src/tools/CronScheduler/types/index.ts +18 -1
- package/src/tools/Map/lazy.tsx +11 -4
- package/src/tools/Uploader/hooks/useClipboardPaste.ts +3 -1
- package/src/tools/index.ts +2 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
11
|
-
import { useCronWeekDays } from '../context/hooks';
|
|
11
|
+
import { useCronWeekDays, useCronSize } from '../context/hooks';
|
|
12
12
|
import type { WeekDay } from '../types';
|
|
13
13
|
|
|
14
14
|
const DAYS: { value: WeekDay; label: string; full: string }[] = [
|
|
@@ -33,6 +33,7 @@ export function DayChips({
|
|
|
33
33
|
className,
|
|
34
34
|
}: DayChipsProps) {
|
|
35
35
|
const { weekDays, toggleWeekDay, setWeekDays } = useCronWeekDays();
|
|
36
|
+
const isSm = useCronSize() === 'sm';
|
|
36
37
|
|
|
37
38
|
// Ensure weekDays is always an array
|
|
38
39
|
const safeWeekDays = Array.isArray(weekDays) ? weekDays : [];
|
|
@@ -54,7 +55,10 @@ export function DayChips({
|
|
|
54
55
|
isWeekendDay,
|
|
55
56
|
className: cn(
|
|
56
57
|
'flex flex-col items-center justify-center',
|
|
57
|
-
'
|
|
58
|
+
'font-medium',
|
|
59
|
+
isSm
|
|
60
|
+
? 'h-6 rounded-md text-[11px] leading-none'
|
|
61
|
+
: 'py-2.5 rounded-lg text-xs',
|
|
58
62
|
'transition-all duration-150',
|
|
59
63
|
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
|
|
60
64
|
'active:scale-[0.97]',
|
|
@@ -76,9 +80,13 @@ export function DayChips({
|
|
|
76
80
|
];
|
|
77
81
|
|
|
78
82
|
return (
|
|
79
|
-
<div className={cn('space-y-3', className)}>
|
|
83
|
+
<div className={cn(isSm ? 'space-y-1.5' : 'space-y-3', className)}>
|
|
80
84
|
{/* Day Grid - full width */}
|
|
81
|
-
<div
|
|
85
|
+
<div
|
|
86
|
+
className={cn('grid grid-cols-7', isSm ? 'gap-1' : 'gap-1')}
|
|
87
|
+
role="group"
|
|
88
|
+
aria-label="Days of week"
|
|
89
|
+
>
|
|
82
90
|
{dayButtons.map((day) => (
|
|
83
91
|
<button
|
|
84
92
|
key={day.value}
|
|
@@ -96,7 +104,7 @@ export function DayChips({
|
|
|
96
104
|
|
|
97
105
|
{/* Quick Presets */}
|
|
98
106
|
{showPresets && (
|
|
99
|
-
<div className=
|
|
107
|
+
<div className={cn('flex', isSm ? 'gap-1' : 'gap-2')}>
|
|
100
108
|
{presets.map((preset) => (
|
|
101
109
|
<PresetButton
|
|
102
110
|
key={preset.label}
|
|
@@ -104,6 +112,7 @@ export function DayChips({
|
|
|
104
112
|
isActive={preset.isActive}
|
|
105
113
|
onClick={() => setWeekDays(preset.days)}
|
|
106
114
|
disabled={disabled}
|
|
115
|
+
compact={isSm}
|
|
107
116
|
/>
|
|
108
117
|
))}
|
|
109
118
|
</div>
|
|
@@ -117,16 +126,20 @@ interface PresetButtonProps {
|
|
|
117
126
|
isActive: boolean;
|
|
118
127
|
onClick: () => void;
|
|
119
128
|
disabled?: boolean;
|
|
129
|
+
compact?: boolean;
|
|
120
130
|
}
|
|
121
131
|
|
|
122
|
-
function PresetButton({ label, isActive, onClick, disabled }: PresetButtonProps) {
|
|
132
|
+
function PresetButton({ label, isActive, onClick, disabled, compact }: PresetButtonProps) {
|
|
123
133
|
return (
|
|
124
134
|
<button
|
|
125
135
|
type="button"
|
|
126
136
|
disabled={disabled}
|
|
127
137
|
onClick={onClick}
|
|
128
138
|
className={cn(
|
|
129
|
-
'flex-1
|
|
139
|
+
'flex-1 rounded-md font-medium',
|
|
140
|
+
compact
|
|
141
|
+
? 'h-6 px-1.5 text-[11px] leading-none'
|
|
142
|
+
: 'px-3 py-1.5 text-xs',
|
|
130
143
|
'transition-colors duration-150',
|
|
131
144
|
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
|
|
132
145
|
isActive
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
11
|
-
import { useCronMonthDays } from '../context/hooks';
|
|
11
|
+
import { useCronMonthDays, useCronSize } from '../context/hooks';
|
|
12
12
|
import type { MonthDay } from '../types';
|
|
13
13
|
|
|
14
14
|
// Generate days 1-31
|
|
@@ -29,6 +29,7 @@ export function MonthDayGrid({
|
|
|
29
29
|
className,
|
|
30
30
|
}: MonthDayGridProps) {
|
|
31
31
|
const { monthDays, toggleMonthDay, setMonthDays } = useCronMonthDays();
|
|
32
|
+
const isSm = useCronSize() === 'sm';
|
|
32
33
|
|
|
33
34
|
// Ensure monthDays is always an array
|
|
34
35
|
const safeMonthDays = Array.isArray(monthDays) ? monthDays : [];
|
|
@@ -61,8 +62,11 @@ export function MonthDayGrid({
|
|
|
61
62
|
day: day as MonthDay,
|
|
62
63
|
isSelected,
|
|
63
64
|
className: cn(
|
|
64
|
-
'
|
|
65
|
-
'
|
|
65
|
+
'flex items-center justify-center',
|
|
66
|
+
'font-medium',
|
|
67
|
+
isSm
|
|
68
|
+
? 'h-7 rounded-[5px] text-[10px] leading-none'
|
|
69
|
+
: 'aspect-square rounded-lg text-sm',
|
|
66
70
|
'transition-all duration-150',
|
|
67
71
|
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
|
|
68
72
|
'active:scale-[0.95]',
|
|
@@ -82,10 +86,10 @@ export function MonthDayGrid({
|
|
|
82
86
|
const selectionCount = safeMonthDays.length;
|
|
83
87
|
|
|
84
88
|
return (
|
|
85
|
-
<div className={cn('space-y-3', className)}>
|
|
89
|
+
<div className={cn(isSm ? 'space-y-1.5' : 'space-y-3', className)}>
|
|
86
90
|
{/* Quick Presets */}
|
|
87
91
|
{showPresets && (
|
|
88
|
-
<div className=
|
|
92
|
+
<div className={cn('flex', isSm ? 'gap-1' : 'gap-2')}>
|
|
89
93
|
{presets.map((preset) => (
|
|
90
94
|
<PresetButton
|
|
91
95
|
key={preset.label}
|
|
@@ -93,16 +97,27 @@ export function MonthDayGrid({
|
|
|
93
97
|
isActive={preset.isActive}
|
|
94
98
|
onClick={() => setMonthDays(preset.days)}
|
|
95
99
|
disabled={disabled}
|
|
100
|
+
compact={isSm}
|
|
96
101
|
/>
|
|
97
102
|
))}
|
|
98
103
|
</div>
|
|
99
104
|
)}
|
|
100
105
|
|
|
101
106
|
{/* Calendar Grid - full width */}
|
|
102
|
-
<div
|
|
107
|
+
<div
|
|
108
|
+
className={cn('grid grid-cols-7', isSm ? 'gap-0.5' : 'gap-1')}
|
|
109
|
+
role="group"
|
|
110
|
+
aria-label="Days of month"
|
|
111
|
+
>
|
|
103
112
|
{gridCells.map((cell) => {
|
|
104
113
|
if (cell.type === 'empty') {
|
|
105
|
-
return
|
|
114
|
+
return (
|
|
115
|
+
<div
|
|
116
|
+
key={cell.key}
|
|
117
|
+
aria-hidden="true"
|
|
118
|
+
className={isSm ? 'h-7' : 'aspect-square'}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
106
121
|
}
|
|
107
122
|
|
|
108
123
|
return (
|
|
@@ -123,7 +138,13 @@ export function MonthDayGrid({
|
|
|
123
138
|
|
|
124
139
|
{/* Selection hint */}
|
|
125
140
|
{selectionCount > 1 && (
|
|
126
|
-
<p
|
|
141
|
+
<p
|
|
142
|
+
aria-live="polite"
|
|
143
|
+
className={cn(
|
|
144
|
+
'text-muted-foreground text-center',
|
|
145
|
+
isSm ? 'text-[10px]' : 'text-xs'
|
|
146
|
+
)}
|
|
147
|
+
>
|
|
127
148
|
{selectionCount} days selected
|
|
128
149
|
</p>
|
|
129
150
|
)}
|
|
@@ -136,16 +157,20 @@ interface PresetButtonProps {
|
|
|
136
157
|
isActive: boolean;
|
|
137
158
|
onClick: () => void;
|
|
138
159
|
disabled?: boolean;
|
|
160
|
+
compact?: boolean;
|
|
139
161
|
}
|
|
140
162
|
|
|
141
|
-
function PresetButton({ label, isActive, onClick, disabled }: PresetButtonProps) {
|
|
163
|
+
function PresetButton({ label, isActive, onClick, disabled, compact }: PresetButtonProps) {
|
|
142
164
|
return (
|
|
143
165
|
<button
|
|
144
166
|
type="button"
|
|
145
167
|
disabled={disabled}
|
|
146
168
|
onClick={onClick}
|
|
147
169
|
className={cn(
|
|
148
|
-
'flex-1
|
|
170
|
+
'flex-1 rounded-md font-medium',
|
|
171
|
+
compact
|
|
172
|
+
? 'h-6 px-1.5 text-[11px] leading-none'
|
|
173
|
+
: 'px-3 py-1.5 text-xs',
|
|
149
174
|
'transition-colors duration-150',
|
|
150
175
|
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
|
|
151
176
|
isActive
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { useState, useCallback, useMemo } from 'react';
|
|
11
11
|
import { Calendar, Copy, Check, ArrowRight } from 'lucide-react';
|
|
12
12
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
13
|
-
import { useCronPreview } from '../context/hooks';
|
|
13
|
+
import { useCronPreview, useCronSize } from '../context/hooks';
|
|
14
14
|
import { CronCheatsheet } from './CronCheatsheet';
|
|
15
15
|
|
|
16
16
|
export interface SchedulePreviewProps {
|
|
@@ -31,6 +31,7 @@ export function SchedulePreview({
|
|
|
31
31
|
className,
|
|
32
32
|
}: SchedulePreviewProps) {
|
|
33
33
|
const { cronExpression, humanDescription, isValid, initialValue } = useCronPreview();
|
|
34
|
+
const isSm = useCronSize() === 'sm';
|
|
34
35
|
|
|
35
36
|
// Check if value has changed from initial
|
|
36
37
|
const hasChanged = useMemo(
|
|
@@ -54,7 +55,8 @@ export function SchedulePreview({
|
|
|
54
55
|
role="status"
|
|
55
56
|
aria-live="polite"
|
|
56
57
|
className={cn(
|
|
57
|
-
'
|
|
58
|
+
'rounded-lg border',
|
|
59
|
+
isSm ? 'px-2 py-1.5' : 'px-3 py-2.5',
|
|
58
60
|
'bg-muted/30 border-border/50',
|
|
59
61
|
!isValid && 'border-destructive/30 bg-destructive/5',
|
|
60
62
|
className
|
|
@@ -62,17 +64,18 @@ export function SchedulePreview({
|
|
|
62
64
|
>
|
|
63
65
|
{/* Human description */}
|
|
64
66
|
<div className="flex items-center justify-between gap-2">
|
|
65
|
-
<div className=
|
|
67
|
+
<div className={cn('flex items-center min-w-0', isSm ? 'gap-1.5' : 'gap-2')}>
|
|
66
68
|
<Calendar
|
|
67
69
|
aria-hidden="true"
|
|
68
70
|
className={cn(
|
|
69
|
-
'
|
|
71
|
+
'shrink-0',
|
|
72
|
+
isSm ? 'h-3.5 w-3.5' : 'h-4 w-4',
|
|
70
73
|
isValid ? 'text-primary' : 'text-destructive'
|
|
71
74
|
)}
|
|
72
75
|
/>
|
|
73
76
|
<span
|
|
74
77
|
className={cn(
|
|
75
|
-
'text-sm',
|
|
78
|
+
isSm ? 'text-xs' : 'text-sm',
|
|
76
79
|
isValid ? 'text-foreground' : 'text-destructive'
|
|
77
80
|
)}
|
|
78
81
|
>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { Tabs, TabsList, TabsTrigger } from '@djangocfg/ui-core/components';
|
|
11
11
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
12
|
-
import { useCronType } from '../context/hooks';
|
|
12
|
+
import { useCronType, useCronSize } from '../context/hooks';
|
|
13
13
|
import type { ScheduleType } from '../types';
|
|
14
14
|
|
|
15
15
|
const SCHEDULE_TYPES: { value: ScheduleType; label: string }[] = [
|
|
@@ -29,9 +29,13 @@ export function ScheduleTypeSelector({
|
|
|
29
29
|
className,
|
|
30
30
|
}: ScheduleTypeSelectorProps) {
|
|
31
31
|
const { type, setType } = useCronType();
|
|
32
|
+
const isSm = useCronSize() === 'sm';
|
|
32
33
|
|
|
33
34
|
const triggerClassName = cn(
|
|
34
|
-
'
|
|
35
|
+
'font-medium',
|
|
36
|
+
isSm
|
|
37
|
+
? 'text-[11px] leading-none px-1 py-0.5 h-6 rounded-[5px]'
|
|
38
|
+
: 'text-xs px-2 py-1.5',
|
|
35
39
|
'data-[state=active]:shadow-sm',
|
|
36
40
|
'transition-all duration-150'
|
|
37
41
|
);
|
|
@@ -49,7 +53,12 @@ export function ScheduleTypeSelector({
|
|
|
49
53
|
onValueChange={(v) => setType(v as ScheduleType)}
|
|
50
54
|
className={cn('w-full', className)}
|
|
51
55
|
>
|
|
52
|
-
<TabsList
|
|
56
|
+
<TabsList
|
|
57
|
+
className={cn(
|
|
58
|
+
'grid w-full grid-cols-4',
|
|
59
|
+
isSm ? 'h-7 p-0.5 gap-0.5' : 'h-9 p-0.5'
|
|
60
|
+
)}
|
|
61
|
+
>
|
|
53
62
|
{triggers.map((trigger) => (
|
|
54
63
|
<TabsTrigger
|
|
55
64
|
key={trigger.value}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from '@djangocfg/ui-core/components';
|
|
16
16
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
17
17
|
import { Clock } from 'lucide-react';
|
|
18
|
-
import { useCronTime } from '../context/hooks';
|
|
18
|
+
import { useCronTime, useCronSize } from '../context/hooks';
|
|
19
19
|
|
|
20
20
|
const HOURS = Array.from({ length: 24 }, (_, i) => i);
|
|
21
21
|
const MINUTES = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55];
|
|
@@ -32,6 +32,7 @@ export function TimeSelector({
|
|
|
32
32
|
className,
|
|
33
33
|
}: TimeSelectorProps) {
|
|
34
34
|
const { hour, minute, setTime } = useCronTime();
|
|
35
|
+
const isSm = useCronSize() === 'sm';
|
|
35
36
|
|
|
36
37
|
const is24h = format === '24h';
|
|
37
38
|
const displayHour = is24h ? hour : (hour % 12) || 12;
|
|
@@ -60,28 +61,50 @@ export function TimeSelector({
|
|
|
60
61
|
|
|
61
62
|
const hours = is24h ? HOURS : Array.from({ length: 12 }, (_, i) => i + 1);
|
|
62
63
|
|
|
64
|
+
// Compact-aware class fragments
|
|
65
|
+
const triggerClassName = cn(
|
|
66
|
+
isSm ? 'w-[58px] h-7 px-2 text-xs' : 'w-[70px] h-9'
|
|
67
|
+
);
|
|
68
|
+
const itemClassName = isSm ? 'text-xs' : undefined;
|
|
69
|
+
|
|
63
70
|
return (
|
|
64
|
-
<div
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
<div
|
|
72
|
+
className={cn(
|
|
73
|
+
'flex items-center',
|
|
74
|
+
isSm ? 'gap-2' : 'gap-3',
|
|
75
|
+
className
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
78
|
+
<div
|
|
79
|
+
className={cn(
|
|
80
|
+
'flex items-center text-muted-foreground',
|
|
81
|
+
isSm ? 'gap-1.5' : 'gap-2'
|
|
82
|
+
)}
|
|
83
|
+
>
|
|
84
|
+
<Clock
|
|
85
|
+
aria-hidden="true"
|
|
86
|
+
className={isSm ? 'h-3.5 w-3.5' : 'h-4 w-4'}
|
|
87
|
+
/>
|
|
88
|
+
<span className={isSm ? 'text-xs' : 'text-sm'}>Run at</span>
|
|
68
89
|
</div>
|
|
69
90
|
|
|
70
|
-
<div
|
|
91
|
+
<div
|
|
92
|
+
className={cn('flex items-center flex-1', isSm ? 'gap-1' : 'gap-1.5')}
|
|
93
|
+
>
|
|
71
94
|
{/* Hour */}
|
|
72
95
|
<Select
|
|
73
96
|
value={displayHour.toString()}
|
|
74
97
|
onValueChange={handleHourChange}
|
|
75
98
|
disabled={disabled}
|
|
76
99
|
>
|
|
77
|
-
<SelectTrigger className=
|
|
100
|
+
<SelectTrigger className={triggerClassName}>
|
|
78
101
|
<SelectValue>
|
|
79
102
|
{displayHour.toString().padStart(2, '0')}
|
|
80
103
|
</SelectValue>
|
|
81
104
|
</SelectTrigger>
|
|
82
105
|
<SelectContent className="max-h-48">
|
|
83
106
|
{hours.map((h) => (
|
|
84
|
-
<SelectItem key={h} value={h.toString()}>
|
|
107
|
+
<SelectItem key={h} value={h.toString()} className={itemClassName}>
|
|
85
108
|
{h.toString().padStart(2, '0')}
|
|
86
109
|
</SelectItem>
|
|
87
110
|
))}
|
|
@@ -96,14 +119,14 @@ export function TimeSelector({
|
|
|
96
119
|
onValueChange={handleMinuteChange}
|
|
97
120
|
disabled={disabled}
|
|
98
121
|
>
|
|
99
|
-
<SelectTrigger className=
|
|
122
|
+
<SelectTrigger className={triggerClassName}>
|
|
100
123
|
<SelectValue>
|
|
101
124
|
{minute.toString().padStart(2, '0')}
|
|
102
125
|
</SelectValue>
|
|
103
126
|
</SelectTrigger>
|
|
104
127
|
<SelectContent className="max-h-48">
|
|
105
128
|
{MINUTES.map((m) => (
|
|
106
|
-
<SelectItem key={m} value={m.toString()}>
|
|
129
|
+
<SelectItem key={m} value={m.toString()} className={itemClassName}>
|
|
107
130
|
{m.toString().padStart(2, '0')}
|
|
108
131
|
</SelectItem>
|
|
109
132
|
))}
|
|
@@ -117,12 +140,12 @@ export function TimeSelector({
|
|
|
117
140
|
onValueChange={handlePeriodChange}
|
|
118
141
|
disabled={disabled}
|
|
119
142
|
>
|
|
120
|
-
<SelectTrigger className=
|
|
143
|
+
<SelectTrigger className={triggerClassName}>
|
|
121
144
|
<SelectValue />
|
|
122
145
|
</SelectTrigger>
|
|
123
146
|
<SelectContent>
|
|
124
|
-
<SelectItem value="AM">AM</SelectItem>
|
|
125
|
-
<SelectItem value="PM">PM</SelectItem>
|
|
147
|
+
<SelectItem value="AM" className={itemClassName}>AM</SelectItem>
|
|
148
|
+
<SelectItem value="PM" className={itemClassName}>PM</SelectItem>
|
|
126
149
|
</SelectContent>
|
|
127
150
|
</Select>
|
|
128
151
|
)}
|
|
@@ -57,6 +57,7 @@ export function CronSchedulerProvider({
|
|
|
57
57
|
value,
|
|
58
58
|
onChange,
|
|
59
59
|
defaultType = 'daily',
|
|
60
|
+
size = 'default',
|
|
60
61
|
}: CronSchedulerProviderProps) {
|
|
61
62
|
// Track if this is initial mount to avoid calling onChange on mount
|
|
62
63
|
const isInitialMount = useRef(true);
|
|
@@ -203,6 +204,8 @@ export function CronSchedulerProvider({
|
|
|
203
204
|
() => ({
|
|
204
205
|
// State
|
|
205
206
|
...state,
|
|
207
|
+
// Config
|
|
208
|
+
size,
|
|
206
209
|
// Computed
|
|
207
210
|
cronExpression,
|
|
208
211
|
humanDescription,
|
|
@@ -219,6 +222,7 @@ export function CronSchedulerProvider({
|
|
|
219
222
|
}),
|
|
220
223
|
[
|
|
221
224
|
state,
|
|
225
|
+
size,
|
|
222
226
|
cronExpression,
|
|
223
227
|
humanDescription,
|
|
224
228
|
initialValue,
|
|
@@ -78,6 +78,14 @@ export function useCronPreview() {
|
|
|
78
78
|
);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Hook for the configured visual density (`default` | `sm`).
|
|
83
|
+
* Returns a stable value — never causes re-renders by itself.
|
|
84
|
+
*/
|
|
85
|
+
export function useCronSize() {
|
|
86
|
+
return useCronSchedulerContext().size;
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
/**
|
|
82
90
|
* Full context access
|
|
83
91
|
* Use sparingly - causes re-render on any state change
|
|
@@ -50,6 +50,7 @@ function CronSchedulerFallback() {
|
|
|
50
50
|
// Re-export types
|
|
51
51
|
export type {
|
|
52
52
|
CronSchedulerProps,
|
|
53
|
+
CronSchedulerSize,
|
|
53
54
|
ScheduleType,
|
|
54
55
|
WeekDay,
|
|
55
56
|
MonthDay,
|
|
@@ -67,6 +68,7 @@ export {
|
|
|
67
68
|
useCronMonthDays,
|
|
68
69
|
useCronCustom,
|
|
69
70
|
useCronPreview,
|
|
71
|
+
useCronSize,
|
|
70
72
|
useCronScheduler,
|
|
71
73
|
} from './context';
|
|
72
74
|
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
export type ScheduleType = 'daily' | 'weekly' | 'monthly' | 'custom';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Visual density of the scheduler fields.
|
|
15
|
+
* - `default` — full-size fields (unchanged).
|
|
16
|
+
* - `sm` — compact fields for narrow side panels / modals (~360-420px).
|
|
17
|
+
*/
|
|
18
|
+
export type CronSchedulerSize = 'default' | 'sm';
|
|
19
|
+
|
|
13
20
|
/** Day of week: 0 = Sunday, 1 = Monday, ..., 6 = Saturday */
|
|
14
21
|
export type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
15
22
|
|
|
@@ -79,7 +86,10 @@ export interface CronSchedulerActions {
|
|
|
79
86
|
export interface CronSchedulerContextValue
|
|
80
87
|
extends CronSchedulerState,
|
|
81
88
|
CronSchedulerComputed,
|
|
82
|
-
CronSchedulerActions {
|
|
89
|
+
CronSchedulerActions {
|
|
90
|
+
/** Visual density of the fields (`default` | `sm`) */
|
|
91
|
+
size: CronSchedulerSize;
|
|
92
|
+
}
|
|
83
93
|
|
|
84
94
|
// ============================================================================
|
|
85
95
|
// Component Props
|
|
@@ -107,6 +117,11 @@ export interface CronSchedulerProps {
|
|
|
107
117
|
inline?: boolean;
|
|
108
118
|
/** Trigger text shown when no schedule is set (compact mode only) */
|
|
109
119
|
placeholder?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Visual density of the fields. `sm` renders smaller, tighter fields
|
|
122
|
+
* suited for narrow side panels / modals. Default: `default`.
|
|
123
|
+
*/
|
|
124
|
+
size?: CronSchedulerSize;
|
|
110
125
|
/** Additional CSS classes */
|
|
111
126
|
className?: string;
|
|
112
127
|
}
|
|
@@ -116,4 +131,6 @@ export interface CronSchedulerProviderProps {
|
|
|
116
131
|
value?: string;
|
|
117
132
|
onChange?: (cron: string) => void;
|
|
118
133
|
defaultType?: ScheduleType;
|
|
134
|
+
/** Visual density propagated to all field components. Default: `default`. */
|
|
135
|
+
size?: CronSchedulerSize;
|
|
119
136
|
}
|
package/src/tools/Map/lazy.tsx
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import * as React from 'react';
|
|
14
14
|
import { createLazyComponent, MapLoadingFallback } from '../../components';
|
|
15
|
+
import type { MapContainerProps } from './components';
|
|
15
16
|
|
|
16
17
|
// ============================================================================
|
|
17
18
|
// Lazy Components
|
|
@@ -22,8 +23,11 @@ import { createLazyComponent, MapLoadingFallback } from '../../components';
|
|
|
22
23
|
*
|
|
23
24
|
* Automatically shows loading state while MapLibre GL loads (~800KB)
|
|
24
25
|
*/
|
|
25
|
-
export const LazyMapContainer = createLazyComponent(
|
|
26
|
-
() =>
|
|
26
|
+
export const LazyMapContainer = createLazyComponent<MapContainerProps>(
|
|
27
|
+
() =>
|
|
28
|
+
import('./components/MapContainer').then((mod) => ({
|
|
29
|
+
default: mod.MapContainer,
|
|
30
|
+
})),
|
|
27
31
|
{
|
|
28
32
|
displayName: 'LazyMapContainer',
|
|
29
33
|
fallback: <MapLoadingFallback minHeight={400} />,
|
|
@@ -33,8 +37,11 @@ export const LazyMapContainer = createLazyComponent(
|
|
|
33
37
|
/**
|
|
34
38
|
* LazyMapView - Lazy-loaded map view (alias for MapContainer)
|
|
35
39
|
*/
|
|
36
|
-
export const LazyMapView = createLazyComponent(
|
|
37
|
-
() =>
|
|
40
|
+
export const LazyMapView = createLazyComponent<Omit<MapContainerProps, 'initialViewport'>>(
|
|
41
|
+
() =>
|
|
42
|
+
import('./components/MapContainer').then((mod) => ({
|
|
43
|
+
default: mod.MapView,
|
|
44
|
+
})),
|
|
38
45
|
{
|
|
39
46
|
displayName: 'LazyMapView',
|
|
40
47
|
fallback: <MapLoadingFallback minHeight={400} />,
|
|
@@ -87,7 +87,9 @@ async function resolveClipboardFiles(
|
|
|
87
87
|
}
|
|
88
88
|
return [file];
|
|
89
89
|
} catch (err) {
|
|
90
|
-
logger.warn('Failed to fetch pasted URL',
|
|
90
|
+
logger.warn('Failed to fetch pasted URL', {
|
|
91
|
+
error: err instanceof Error ? err.message : String(err),
|
|
92
|
+
});
|
|
91
93
|
return [];
|
|
92
94
|
}
|
|
93
95
|
}
|
package/src/tools/index.ts
CHANGED
|
@@ -112,6 +112,7 @@ export {
|
|
|
112
112
|
useCronMonthDays,
|
|
113
113
|
useCronCustom,
|
|
114
114
|
useCronPreview,
|
|
115
|
+
useCronSize,
|
|
115
116
|
useCronScheduler,
|
|
116
117
|
// Utilities
|
|
117
118
|
buildCron,
|
|
@@ -128,6 +129,7 @@ export {
|
|
|
128
129
|
} from './CronScheduler';
|
|
129
130
|
export type {
|
|
130
131
|
CronSchedulerProps,
|
|
132
|
+
CronSchedulerSize,
|
|
131
133
|
ScheduleType,
|
|
132
134
|
WeekDay,
|
|
133
135
|
MonthDay,
|