@djangocfg/ui-core 2.1.382 → 2.1.384
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 +5 -12
- package/src/components/boundary/boundary.story.tsx +0 -191
- package/src/components/data/avatar/avatar.story.tsx +0 -115
- package/src/components/data/badge/badge.story.tsx +0 -56
- package/src/components/data/calendar/calendar.story.tsx +0 -127
- package/src/components/data/carousel/carousel.story.tsx +0 -122
- package/src/components/data/progress/progress.story.tsx +0 -97
- package/src/components/data/table/table.story.tsx +0 -148
- package/src/components/data/toggle/toggle.story.tsx +0 -104
- package/src/components/data/toggle-group/toggle-group.story.tsx +0 -118
- package/src/components/feedback/alert/alert.story.tsx +0 -77
- package/src/components/feedback/empty/empty.story.tsx +0 -115
- package/src/components/feedback/preloader/preloader.story.tsx +0 -86
- package/src/components/feedback/spinner/spinner.story.tsx +0 -66
- package/src/components/forms/button/button.story.tsx +0 -116
- package/src/components/forms/button-download/button-download.story.tsx +0 -112
- package/src/components/forms/button-group/button-group.story.tsx +0 -79
- package/src/components/forms/checkbox/checkbox.story.tsx +0 -89
- package/src/components/forms/input/input.story.tsx +0 -77
- package/src/components/forms/input-group/input-group.story.tsx +0 -119
- package/src/components/forms/input-otp/input-otp.story.tsx +0 -105
- package/src/components/forms/label/label.story.tsx +0 -52
- package/src/components/forms/radio-group/radio-group.story.tsx +0 -113
- package/src/components/forms/slider/slider.story.tsx +0 -134
- package/src/components/forms/switch/switch.story.tsx +0 -98
- package/src/components/forms/textarea/textarea.story.tsx +0 -94
- package/src/components/layout/aspect-ratio/aspect-ratio.story.tsx +0 -94
- package/src/components/layout/card/card.story.tsx +0 -105
- package/src/components/layout/resizable/resizable.story.tsx +0 -119
- package/src/components/layout/scroll-area/scroll-area.story.tsx +0 -172
- package/src/components/layout/separator/separator.story.tsx +0 -69
- package/src/components/layout/skeleton/skeleton.story.tsx +0 -101
- package/src/components/navigation/accordion/accordion.story.tsx +0 -110
- package/src/components/navigation/collapsible/collapsible.story.tsx +0 -133
- package/src/components/navigation/command/command.story.tsx +0 -121
- package/src/components/navigation/context-menu/context-menu.story.tsx +0 -125
- package/src/components/navigation/dropdown-menu/dropdown-menu.story.tsx +0 -208
- package/src/components/navigation/menubar/menubar.story.tsx +0 -152
- package/src/components/navigation/navigation-menu/navigation-menu.story.tsx +0 -154
- package/src/components/navigation/tabs/tabs.story.tsx +0 -98
- package/src/components/overlay/alert-dialog/alert-dialog.story.tsx +0 -104
- package/src/components/overlay/dialog/dialog.story.tsx +0 -212
- package/src/components/overlay/drawer/drawer.story.tsx +0 -359
- package/src/components/overlay/hover-card/hover-card.story.tsx +0 -102
- package/src/components/overlay/popover/popover.story.tsx +0 -127
- package/src/components/overlay/responsive-sheet/responsive-sheet.story.tsx +0 -117
- package/src/components/overlay/sheet/sheet.story.tsx +0 -148
- package/src/components/overlay/tooltip/tooltip.story.tsx +0 -139
- package/src/components/select/combobox-async.story.tsx +0 -215
- package/src/components/select/combobox.story.tsx +0 -226
- package/src/components/select/country-select.story.tsx +0 -261
- package/src/components/select/language-select.story.tsx +0 -264
- package/src/components/select/multi-select.story.tsx +0 -122
- package/src/components/select/select.story.tsx +0 -112
- package/src/components/specialized/copy/copy.story.tsx +0 -77
- package/src/components/specialized/flag/flag.story.tsx +0 -82
- package/src/components/specialized/image-with-fallback/image-with-fallback.story.tsx +0 -105
- package/src/components/specialized/kbd/kbd.story.tsx +0 -113
- package/src/lib/dialog-service/dialog-service.story.tsx +0 -263
- package/src/stories/index.ts +0 -28
- package/src/styles/theme/theme-tokens.story.tsx +0 -157
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
2
|
-
import { ImageWithFallback } from '.';
|
|
3
|
-
|
|
4
|
-
export default defineStory({
|
|
5
|
-
title: 'Core/ImageWithFallback',
|
|
6
|
-
component: ImageWithFallback,
|
|
7
|
-
description: 'Image component with loading states and fallbacks.',
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
export const Interactive = () => {
|
|
11
|
-
const [fallbackIcon] = useSelect('fallbackIcon', {
|
|
12
|
-
options: ['car', 'image', 'user', 'package', 'location'] as const,
|
|
13
|
-
defaultValue: 'image',
|
|
14
|
-
label: 'Fallback Icon',
|
|
15
|
-
description: 'Icon shown on error or missing src',
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ImageWithFallback
|
|
20
|
-
src="https://images.unsplash.com/photo-1494976388531-d1058494cdd8?w=400"
|
|
21
|
-
alt="Car"
|
|
22
|
-
fallbackIcon={fallbackIcon}
|
|
23
|
-
className="h-48 w-72 rounded-lg"
|
|
24
|
-
/>
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const Default = () => (
|
|
29
|
-
<ImageWithFallback
|
|
30
|
-
src="https://images.unsplash.com/photo-1494976388531-d1058494cdd8?w=400"
|
|
31
|
-
alt="Car"
|
|
32
|
-
className="h-48 w-72 rounded-lg"
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
export const WithFallbackCar = () => (
|
|
37
|
-
<ImageWithFallback
|
|
38
|
-
src=""
|
|
39
|
-
alt="Missing car image"
|
|
40
|
-
fallbackIcon="car"
|
|
41
|
-
className="h-48 w-72 rounded-lg"
|
|
42
|
-
/>
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
export const WithFallbackUser = () => (
|
|
46
|
-
<ImageWithFallback
|
|
47
|
-
src=""
|
|
48
|
-
alt="Missing user avatar"
|
|
49
|
-
fallbackIcon="user"
|
|
50
|
-
className="h-24 w-24 rounded-full"
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
export const WithFallbackLocation = () => (
|
|
55
|
-
<ImageWithFallback
|
|
56
|
-
src=""
|
|
57
|
-
alt="Missing location"
|
|
58
|
-
fallbackIcon="location"
|
|
59
|
-
className="h-32 w-32 rounded-lg"
|
|
60
|
-
/>
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
export const BrokenImage = () => (
|
|
64
|
-
<ImageWithFallback
|
|
65
|
-
src="https://invalid-url-that-does-not-exist.com/image.jpg"
|
|
66
|
-
alt="Broken image"
|
|
67
|
-
fallbackIcon="image"
|
|
68
|
-
className="h-48 w-72 rounded-lg"
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
export const CustomFallback = () => (
|
|
73
|
-
<ImageWithFallback
|
|
74
|
-
src=""
|
|
75
|
-
alt="Custom fallback"
|
|
76
|
-
fallbackContent={
|
|
77
|
-
<div className="flex flex-col items-center gap-2 text-muted-foreground">
|
|
78
|
-
<span className="text-4xl">🚗</span>
|
|
79
|
-
<span className="text-sm">No image available</span>
|
|
80
|
-
</div>
|
|
81
|
-
}
|
|
82
|
-
className="h-48 w-72 rounded-lg border bg-muted/20"
|
|
83
|
-
/>
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
export const Gallery = () => (
|
|
87
|
-
<div className="grid grid-cols-3 gap-4">
|
|
88
|
-
<ImageWithFallback
|
|
89
|
-
src="https://images.unsplash.com/photo-1494976388531-d1058494cdd8?w=200"
|
|
90
|
-
alt="Car 1"
|
|
91
|
-
className="h-32 w-full rounded-lg"
|
|
92
|
-
/>
|
|
93
|
-
<ImageWithFallback
|
|
94
|
-
src=""
|
|
95
|
-
alt="Missing"
|
|
96
|
-
fallbackIcon="car"
|
|
97
|
-
className="h-32 w-full rounded-lg"
|
|
98
|
-
/>
|
|
99
|
-
<ImageWithFallback
|
|
100
|
-
src="https://images.unsplash.com/photo-1503376780353-7e6692767b70?w=200"
|
|
101
|
-
alt="Car 2"
|
|
102
|
-
className="h-32 w-full rounded-lg"
|
|
103
|
-
/>
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { defineStory, useSelect } from '@djangocfg/playground';
|
|
2
|
-
import { Kbd, KbdGroup } from '.';
|
|
3
|
-
|
|
4
|
-
export default defineStory({
|
|
5
|
-
title: 'Core/Kbd',
|
|
6
|
-
component: Kbd,
|
|
7
|
-
description: 'Keyboard key indicator for shortcuts.',
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
export const Interactive = () => {
|
|
11
|
-
const [size] = useSelect('size', {
|
|
12
|
-
options: ['xs', 'sm', 'default', 'lg'] as const,
|
|
13
|
-
defaultValue: 'default',
|
|
14
|
-
label: 'Size',
|
|
15
|
-
description: 'Kbd size',
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
return <Kbd size={size}>⌘</Kbd>;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const Default = () => <Kbd>⌘</Kbd>;
|
|
22
|
-
|
|
23
|
-
export const Sizes = () => (
|
|
24
|
-
<div className="flex items-center gap-4">
|
|
25
|
-
<Kbd size="xs">⌘</Kbd>
|
|
26
|
-
<Kbd size="sm">⌘</Kbd>
|
|
27
|
-
<Kbd size="default">⌘</Kbd>
|
|
28
|
-
<Kbd size="lg">⌘</Kbd>
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
export const Shortcuts = () => (
|
|
33
|
-
<div className="space-y-4">
|
|
34
|
-
<div className="flex items-center gap-2">
|
|
35
|
-
<span className="text-sm w-32">Copy</span>
|
|
36
|
-
<KbdGroup>
|
|
37
|
-
<Kbd>⌘</Kbd>
|
|
38
|
-
<Kbd>C</Kbd>
|
|
39
|
-
</KbdGroup>
|
|
40
|
-
</div>
|
|
41
|
-
<div className="flex items-center gap-2">
|
|
42
|
-
<span className="text-sm w-32">Paste</span>
|
|
43
|
-
<KbdGroup>
|
|
44
|
-
<Kbd>⌘</Kbd>
|
|
45
|
-
<Kbd>V</Kbd>
|
|
46
|
-
</KbdGroup>
|
|
47
|
-
</div>
|
|
48
|
-
<div className="flex items-center gap-2">
|
|
49
|
-
<span className="text-sm w-32">Undo</span>
|
|
50
|
-
<KbdGroup>
|
|
51
|
-
<Kbd>⌘</Kbd>
|
|
52
|
-
<Kbd>Z</Kbd>
|
|
53
|
-
</KbdGroup>
|
|
54
|
-
</div>
|
|
55
|
-
<div className="flex items-center gap-2">
|
|
56
|
-
<span className="text-sm w-32">Save</span>
|
|
57
|
-
<KbdGroup>
|
|
58
|
-
<Kbd>⌘</Kbd>
|
|
59
|
-
<Kbd>S</Kbd>
|
|
60
|
-
</KbdGroup>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
export const ComplexShortcuts = () => (
|
|
66
|
-
<div className="space-y-4">
|
|
67
|
-
<div className="flex items-center gap-2">
|
|
68
|
-
<span className="text-sm w-40">Command Palette</span>
|
|
69
|
-
<KbdGroup>
|
|
70
|
-
<Kbd>⌘</Kbd>
|
|
71
|
-
<Kbd>⇧</Kbd>
|
|
72
|
-
<Kbd>P</Kbd>
|
|
73
|
-
</KbdGroup>
|
|
74
|
-
</div>
|
|
75
|
-
<div className="flex items-center gap-2">
|
|
76
|
-
<span className="text-sm w-40">Go to Definition</span>
|
|
77
|
-
<KbdGroup>
|
|
78
|
-
<Kbd>⌘</Kbd>
|
|
79
|
-
<Kbd>Click</Kbd>
|
|
80
|
-
</KbdGroup>
|
|
81
|
-
</div>
|
|
82
|
-
<div className="flex items-center gap-2">
|
|
83
|
-
<span className="text-sm w-40">Toggle Sidebar</span>
|
|
84
|
-
<KbdGroup>
|
|
85
|
-
<Kbd>⌘</Kbd>
|
|
86
|
-
<Kbd>B</Kbd>
|
|
87
|
-
</KbdGroup>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
export const Keys = () => (
|
|
93
|
-
<div className="flex flex-wrap gap-2">
|
|
94
|
-
<Kbd>⌘</Kbd>
|
|
95
|
-
<Kbd>⌥</Kbd>
|
|
96
|
-
<Kbd>⇧</Kbd>
|
|
97
|
-
<Kbd>⌃</Kbd>
|
|
98
|
-
<Kbd>⏎</Kbd>
|
|
99
|
-
<Kbd>⌫</Kbd>
|
|
100
|
-
<Kbd>⇥</Kbd>
|
|
101
|
-
<Kbd>⎋</Kbd>
|
|
102
|
-
<Kbd>↑</Kbd>
|
|
103
|
-
<Kbd>↓</Kbd>
|
|
104
|
-
<Kbd>←</Kbd>
|
|
105
|
-
<Kbd>→</Kbd>
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
export const InText = () => (
|
|
110
|
-
<p className="text-sm text-muted-foreground">
|
|
111
|
-
Press <Kbd size="sm">⌘</Kbd> + <Kbd size="sm">K</Kbd> to open the command palette.
|
|
112
|
-
</p>
|
|
113
|
-
);
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import { defineStory } from '@djangocfg/playground';
|
|
3
|
-
import { Button } from '../../components/forms/button';
|
|
4
|
-
import { DialogProvider } from './DialogProvider';
|
|
5
|
-
import { useDialog } from './hooks';
|
|
6
|
-
|
|
7
|
-
export default defineStory({
|
|
8
|
-
title: 'Lib/DialogService',
|
|
9
|
-
component: DialogProvider,
|
|
10
|
-
description: 'Global dialog service for alert, confirm, and prompt dialogs. Uses CustomEvents to work from anywhere in the app. Supports i18n and keyboard shortcuts.',
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// Wrapper component to provide DialogProvider context
|
|
14
|
-
function StoryWrapper({ children }: { children: React.ReactNode }) {
|
|
15
|
-
return <DialogProvider>{children}</DialogProvider>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Demo component using the hook
|
|
19
|
-
function AlertDemo() {
|
|
20
|
-
const { alert } = useDialog();
|
|
21
|
-
|
|
22
|
-
const handleSimpleAlert = useCallback(async () => {
|
|
23
|
-
await alert('This is a simple alert message!');
|
|
24
|
-
console.log('Alert closed');
|
|
25
|
-
}, [alert]);
|
|
26
|
-
|
|
27
|
-
const handleAlertWithTitle = useCallback(async () => {
|
|
28
|
-
await alert({
|
|
29
|
-
title: 'Success!',
|
|
30
|
-
message: 'Your changes have been saved successfully.',
|
|
31
|
-
});
|
|
32
|
-
console.log('Alert with title closed');
|
|
33
|
-
}, [alert]);
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<div className="flex gap-2">
|
|
37
|
-
<Button onClick={handleSimpleAlert}>Simple Alert</Button>
|
|
38
|
-
<Button variant="outline" onClick={handleAlertWithTitle}>
|
|
39
|
-
Alert with Title
|
|
40
|
-
</Button>
|
|
41
|
-
</div>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const Alert = () => (
|
|
46
|
-
<StoryWrapper>
|
|
47
|
-
<AlertDemo />
|
|
48
|
-
</StoryWrapper>
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
// Confirm demo
|
|
52
|
-
function ConfirmDemo() {
|
|
53
|
-
const { confirm, alert } = useDialog();
|
|
54
|
-
|
|
55
|
-
const handleSimpleConfirm = useCallback(async () => {
|
|
56
|
-
const result = await confirm('Are you sure you want to proceed?');
|
|
57
|
-
await alert(`You clicked: ${result ? 'Confirm' : 'Cancel'}`);
|
|
58
|
-
}, [confirm, alert]);
|
|
59
|
-
|
|
60
|
-
const handleDestructiveConfirm = useCallback(async () => {
|
|
61
|
-
const result = await confirm({
|
|
62
|
-
title: 'Delete Item',
|
|
63
|
-
message: 'This action cannot be undone. Are you sure you want to delete this item?',
|
|
64
|
-
confirmText: 'Yes, Delete',
|
|
65
|
-
cancelText: 'Keep It',
|
|
66
|
-
variant: 'destructive',
|
|
67
|
-
});
|
|
68
|
-
await alert(`You clicked: ${result ? 'Delete' : 'Keep'}`);
|
|
69
|
-
}, [confirm, alert]);
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<div className="flex gap-2">
|
|
73
|
-
<Button onClick={handleSimpleConfirm}>Simple Confirm</Button>
|
|
74
|
-
<Button variant="destructive" onClick={handleDestructiveConfirm}>
|
|
75
|
-
Destructive Confirm
|
|
76
|
-
</Button>
|
|
77
|
-
</div>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export const Confirm = () => (
|
|
82
|
-
<StoryWrapper>
|
|
83
|
-
<ConfirmDemo />
|
|
84
|
-
</StoryWrapper>
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
// Prompt demo
|
|
88
|
-
function PromptDemo() {
|
|
89
|
-
const { prompt, alert } = useDialog();
|
|
90
|
-
|
|
91
|
-
const handleSimplePrompt = useCallback(async () => {
|
|
92
|
-
const result = await prompt('What is your name?');
|
|
93
|
-
if (result) {
|
|
94
|
-
await alert(`Hello, ${result}!`);
|
|
95
|
-
} else {
|
|
96
|
-
await alert('You cancelled the prompt.');
|
|
97
|
-
}
|
|
98
|
-
}, [prompt, alert]);
|
|
99
|
-
|
|
100
|
-
const handlePromptWithDefault = useCallback(async () => {
|
|
101
|
-
const result = await prompt({
|
|
102
|
-
title: 'Edit Name',
|
|
103
|
-
message: 'Enter your display name:',
|
|
104
|
-
defaultValue: 'John Doe',
|
|
105
|
-
placeholder: 'Enter name...',
|
|
106
|
-
confirmText: 'Save',
|
|
107
|
-
cancelText: 'Cancel',
|
|
108
|
-
});
|
|
109
|
-
if (result) {
|
|
110
|
-
await alert(`Name updated to: ${result}`);
|
|
111
|
-
}
|
|
112
|
-
}, [prompt, alert]);
|
|
113
|
-
|
|
114
|
-
const handleEmailPrompt = useCallback(async () => {
|
|
115
|
-
const result = await prompt({
|
|
116
|
-
title: 'Subscribe',
|
|
117
|
-
message: 'Enter your email to subscribe to our newsletter:',
|
|
118
|
-
placeholder: 'email@example.com',
|
|
119
|
-
inputType: 'email',
|
|
120
|
-
confirmText: 'Subscribe',
|
|
121
|
-
});
|
|
122
|
-
if (result) {
|
|
123
|
-
await alert(`Subscribed with: ${result}`);
|
|
124
|
-
}
|
|
125
|
-
}, [prompt, alert]);
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<div className="flex gap-2 flex-wrap">
|
|
129
|
-
<Button onClick={handleSimplePrompt}>Simple Prompt</Button>
|
|
130
|
-
<Button variant="outline" onClick={handlePromptWithDefault}>
|
|
131
|
-
Prompt with Default
|
|
132
|
-
</Button>
|
|
133
|
-
<Button variant="secondary" onClick={handleEmailPrompt}>
|
|
134
|
-
Email Prompt
|
|
135
|
-
</Button>
|
|
136
|
-
</div>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export const Prompt = () => (
|
|
141
|
-
<StoryWrapper>
|
|
142
|
-
<PromptDemo />
|
|
143
|
-
</StoryWrapper>
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
// Queue demo - multiple dialogs in sequence
|
|
147
|
-
function QueueDemo() {
|
|
148
|
-
const { alert, confirm, prompt } = useDialog();
|
|
149
|
-
|
|
150
|
-
const handleQueue = useCallback(async () => {
|
|
151
|
-
await alert('This is step 1 of 3');
|
|
152
|
-
const proceed = await confirm('Do you want to continue to step 2?');
|
|
153
|
-
if (!proceed) {
|
|
154
|
-
await alert('You cancelled the sequence.');
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const name = await prompt({
|
|
158
|
-
title: 'Step 3',
|
|
159
|
-
message: 'Enter your name to complete:',
|
|
160
|
-
});
|
|
161
|
-
if (name) {
|
|
162
|
-
await alert(`Sequence complete! Hello, ${name}!`);
|
|
163
|
-
} else {
|
|
164
|
-
await alert('Sequence cancelled at step 3.');
|
|
165
|
-
}
|
|
166
|
-
}, [alert, confirm, prompt]);
|
|
167
|
-
|
|
168
|
-
return (
|
|
169
|
-
<Button onClick={handleQueue}>
|
|
170
|
-
Start Dialog Sequence
|
|
171
|
-
</Button>
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export const Queue = () => (
|
|
176
|
-
<StoryWrapper>
|
|
177
|
-
<QueueDemo />
|
|
178
|
-
</StoryWrapper>
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
// Window.dialog API demo (vanilla JS style)
|
|
182
|
-
function WindowDialogDemo() {
|
|
183
|
-
const handleWindowAlert = useCallback(() => {
|
|
184
|
-
window.dialog.alert('Called via window.dialog.alert()');
|
|
185
|
-
}, []);
|
|
186
|
-
|
|
187
|
-
const handleWindowConfirm = useCallback(async () => {
|
|
188
|
-
const result = await window.dialog.confirm('Called via window.dialog.confirm()');
|
|
189
|
-
window.dialog.alert(`Result: ${result}`);
|
|
190
|
-
}, []);
|
|
191
|
-
|
|
192
|
-
const handleWindowPrompt = useCallback(async () => {
|
|
193
|
-
const result = await window.dialog.prompt({
|
|
194
|
-
title: 'window.dialog.prompt()',
|
|
195
|
-
message: 'This works from vanilla JS too!',
|
|
196
|
-
defaultValue: 'Hello',
|
|
197
|
-
});
|
|
198
|
-
if (result) {
|
|
199
|
-
window.dialog.alert(`You entered: ${result}`);
|
|
200
|
-
}
|
|
201
|
-
}, []);
|
|
202
|
-
|
|
203
|
-
return (
|
|
204
|
-
<div className="space-y-4">
|
|
205
|
-
<p className="text-sm text-muted-foreground">
|
|
206
|
-
These buttons use <code>window.dialog.*</code> directly - works from any JS code!
|
|
207
|
-
</p>
|
|
208
|
-
<div className="flex gap-2">
|
|
209
|
-
<Button variant="outline" onClick={handleWindowAlert}>
|
|
210
|
-
window.dialog.alert()
|
|
211
|
-
</Button>
|
|
212
|
-
<Button variant="outline" onClick={handleWindowConfirm}>
|
|
213
|
-
window.dialog.confirm()
|
|
214
|
-
</Button>
|
|
215
|
-
<Button variant="outline" onClick={handleWindowPrompt}>
|
|
216
|
-
window.dialog.prompt()
|
|
217
|
-
</Button>
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export const WindowDialogAPI = () => (
|
|
224
|
-
<StoryWrapper>
|
|
225
|
-
<WindowDialogDemo />
|
|
226
|
-
</StoryWrapper>
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
// Keyboard shortcuts demo
|
|
230
|
-
function HotkeysDemo() {
|
|
231
|
-
const { alert, confirm } = useDialog();
|
|
232
|
-
|
|
233
|
-
const handleHotkeysDemo = useCallback(async () => {
|
|
234
|
-
await alert({
|
|
235
|
-
title: 'Keyboard Shortcuts',
|
|
236
|
-
message: 'Press Enter to close this alert, or wait and click OK.',
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const result = await confirm({
|
|
240
|
-
title: 'Confirm with Keyboard',
|
|
241
|
-
message: 'Press Enter to confirm, Escape to cancel.',
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
await alert(`You pressed: ${result ? 'Enter (Confirm)' : 'Escape (Cancel)'}`);
|
|
245
|
-
}, [alert, confirm]);
|
|
246
|
-
|
|
247
|
-
return (
|
|
248
|
-
<div className="space-y-4">
|
|
249
|
-
<p className="text-sm text-muted-foreground">
|
|
250
|
-
Dialogs support keyboard shortcuts: <kbd className="px-1.5 py-0.5 bg-muted rounded text-xs">Enter</kbd> to confirm, <kbd className="px-1.5 py-0.5 bg-muted rounded text-xs">Escape</kbd> to cancel.
|
|
251
|
-
</p>
|
|
252
|
-
<Button onClick={handleHotkeysDemo}>
|
|
253
|
-
Test Keyboard Shortcuts
|
|
254
|
-
</Button>
|
|
255
|
-
</div>
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export const KeyboardShortcuts = () => (
|
|
260
|
-
<StoryWrapper>
|
|
261
|
-
<HotkeysDemo />
|
|
262
|
-
</StoryWrapper>
|
|
263
|
-
);
|
package/src/stories/index.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI-Core story modules registry.
|
|
3
|
-
*
|
|
4
|
-
* Re-export stories through a package subpath instead of deep importing files from apps.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { StoryModule } from '@djangocfg/playground';
|
|
8
|
-
|
|
9
|
-
import * as Button from '../components/forms/button/button.story';
|
|
10
|
-
import * as Input from '../components/forms/input/input.story';
|
|
11
|
-
import * as Select from '../components/select/select.story';
|
|
12
|
-
import * as Slider from '../components/forms/slider/slider.story';
|
|
13
|
-
import * as Dialog from '../components/overlay/dialog/dialog.story';
|
|
14
|
-
import * as Tabs from '../components/navigation/tabs/tabs.story';
|
|
15
|
-
import * as Popover from '../components/overlay/popover/popover.story';
|
|
16
|
-
import * as Tooltip from '../components/overlay/tooltip/tooltip.story';
|
|
17
|
-
|
|
18
|
-
export const uiCoreStoryModules: Record<string, StoryModule> = {
|
|
19
|
-
'button.story.tsx': Button,
|
|
20
|
-
'input.story.tsx': Input,
|
|
21
|
-
'select.story.tsx': Select,
|
|
22
|
-
'slider.story.tsx': Slider,
|
|
23
|
-
'dialog.story.tsx': Dialog,
|
|
24
|
-
'tabs.story.tsx': Tabs,
|
|
25
|
-
'popover.story.tsx': Popover,
|
|
26
|
-
'tooltip.story.tsx': Tooltip,
|
|
27
|
-
};
|
|
28
|
-
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { defineStory } from '@djangocfg/playground';
|
|
2
|
-
|
|
3
|
-
export default defineStory({
|
|
4
|
-
title: 'Theme/Tokens',
|
|
5
|
-
description: 'Visual reference for all semantic CSS color tokens. Use these classes — never raw Tailwind color-scale classes (amber-500 etc).',
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
9
|
-
|
|
10
|
-
function TokenRow({ label, bg, text, border }: { label: string; bg: string; text: string; border: string }) {
|
|
11
|
-
return (
|
|
12
|
-
<div className={`flex items-center justify-between rounded-md border px-4 py-3 ${bg} ${border}`}>
|
|
13
|
-
<span className={`text-sm font-medium ${text}`}>{label}</span>
|
|
14
|
-
<div className="flex gap-2 font-mono text-xs opacity-70">
|
|
15
|
-
<code className={text}>{bg}</code>
|
|
16
|
-
<code className={text}>{text}</code>
|
|
17
|
-
<code className={text}>{border}</code>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
|
24
|
-
return (
|
|
25
|
-
<div className="space-y-2">
|
|
26
|
-
<h3 className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">{title}</h3>
|
|
27
|
-
<div className="space-y-2">{children}</div>
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function SwatchRow({ name, bgClass }: { name: string; bgClass: string }) {
|
|
33
|
-
return (
|
|
34
|
-
<div className="flex items-center gap-3">
|
|
35
|
-
<div className={`h-8 w-16 rounded border border-border ${bgClass}`} />
|
|
36
|
-
<code className="text-xs text-foreground">{name}</code>
|
|
37
|
-
</div>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ─── Stories ──────────────────────────────────────────────────────────────────
|
|
42
|
-
|
|
43
|
-
export const StatusSurfaces = () => (
|
|
44
|
-
<div className="space-y-6 max-w-2xl">
|
|
45
|
-
<p className="text-sm text-muted-foreground">
|
|
46
|
-
Status banners — use <code className="text-xs bg-code text-code-foreground rounded px-1">bg-*-background</code>,{' '}
|
|
47
|
-
<code className="text-xs bg-code text-code-foreground rounded px-1">text-*-foreground</code>,{' '}
|
|
48
|
-
<code className="text-xs bg-code text-code-foreground rounded px-1">border-*-border</code>
|
|
49
|
-
</p>
|
|
50
|
-
|
|
51
|
-
<Section title="Warning">
|
|
52
|
-
<TokenRow
|
|
53
|
-
label="⚠ You're seeing a preview. Subscribe for full access."
|
|
54
|
-
bg="bg-warning-background"
|
|
55
|
-
text="text-warning-foreground"
|
|
56
|
-
border="border border-warning-border/50"
|
|
57
|
-
/>
|
|
58
|
-
</Section>
|
|
59
|
-
|
|
60
|
-
<Section title="Success">
|
|
61
|
-
<TokenRow
|
|
62
|
-
label="✓ Operation completed successfully."
|
|
63
|
-
bg="bg-success-background"
|
|
64
|
-
text="text-success-foreground"
|
|
65
|
-
border="border border-success-border/50"
|
|
66
|
-
/>
|
|
67
|
-
</Section>
|
|
68
|
-
|
|
69
|
-
<Section title="Destructive">
|
|
70
|
-
<TokenRow
|
|
71
|
-
label="✕ Something went wrong. Please try again."
|
|
72
|
-
bg="bg-destructive-background"
|
|
73
|
-
text="text-destructive"
|
|
74
|
-
border="border border-destructive-border/50"
|
|
75
|
-
/>
|
|
76
|
-
</Section>
|
|
77
|
-
|
|
78
|
-
<Section title="Info">
|
|
79
|
-
<TokenRow
|
|
80
|
-
label="ℹ New features are available in your plan."
|
|
81
|
-
bg="bg-info-background"
|
|
82
|
-
text="text-info-foreground"
|
|
83
|
-
border="border border-info-border/50"
|
|
84
|
-
/>
|
|
85
|
-
</Section>
|
|
86
|
-
</div>
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
export const BaseColors = () => (
|
|
90
|
-
<div className="space-y-6 max-w-xl">
|
|
91
|
-
<Section title="Base">
|
|
92
|
-
<div className="grid grid-cols-2 gap-3">
|
|
93
|
-
<SwatchRow name="bg-background" bgClass="bg-background" />
|
|
94
|
-
<SwatchRow name="bg-foreground" bgClass="bg-foreground" />
|
|
95
|
-
<SwatchRow name="bg-card" bgClass="bg-card" />
|
|
96
|
-
<SwatchRow name="bg-muted" bgClass="bg-muted" />
|
|
97
|
-
<SwatchRow name="bg-accent" bgClass="bg-accent" />
|
|
98
|
-
<SwatchRow name="bg-border" bgClass="bg-border" />
|
|
99
|
-
</div>
|
|
100
|
-
</Section>
|
|
101
|
-
|
|
102
|
-
<Section title="Brand">
|
|
103
|
-
<div className="grid grid-cols-2 gap-3">
|
|
104
|
-
<SwatchRow name="bg-primary" bgClass="bg-primary" />
|
|
105
|
-
<SwatchRow name="bg-secondary" bgClass="bg-secondary" />
|
|
106
|
-
</div>
|
|
107
|
-
</Section>
|
|
108
|
-
|
|
109
|
-
<Section title="Status accents (icon color)">
|
|
110
|
-
<div className="grid grid-cols-2 gap-3">
|
|
111
|
-
<SwatchRow name="bg-warning" bgClass="bg-warning" />
|
|
112
|
-
<SwatchRow name="bg-success" bgClass="bg-success" />
|
|
113
|
-
<SwatchRow name="bg-destructive" bgClass="bg-destructive" />
|
|
114
|
-
<SwatchRow name="bg-info" bgClass="bg-info" />
|
|
115
|
-
</div>
|
|
116
|
-
</Section>
|
|
117
|
-
</div>
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
export const CodeSurface = () => (
|
|
121
|
-
<div className="space-y-4 max-w-xl">
|
|
122
|
-
<Section title="Code tokens">
|
|
123
|
-
<div className="rounded-md border border-code-border bg-code text-code-foreground p-4 font-mono text-sm">
|
|
124
|
-
<div>bg-code / text-code-foreground / border-code-border</div>
|
|
125
|
-
<div className="mt-2 text-xs opacity-60">Used by PrettyCode, MarkdownMessage code fences</div>
|
|
126
|
-
</div>
|
|
127
|
-
<div className="text-sm">
|
|
128
|
-
Inline:{' '}
|
|
129
|
-
<code className="rounded bg-code-inline px-1.5 py-0.5 text-code-inline-foreground text-xs">
|
|
130
|
-
const x = 42
|
|
131
|
-
</code>
|
|
132
|
-
</div>
|
|
133
|
-
</Section>
|
|
134
|
-
|
|
135
|
-
<Section title="Sidebar tokens">
|
|
136
|
-
<div className="rounded-md border border-sidebar-border bg-sidebar p-4 space-y-1 text-sidebar-foreground text-sm">
|
|
137
|
-
<div className="font-semibold">bg-sidebar / text-sidebar-foreground</div>
|
|
138
|
-
<div className="text-xs opacity-60">Used by the app sidebar chrome</div>
|
|
139
|
-
<div className="mt-2 rounded bg-sidebar-accent px-2 py-1 text-sidebar-accent-foreground text-xs">
|
|
140
|
-
bg-sidebar-accent — hover state
|
|
141
|
-
</div>
|
|
142
|
-
</div>
|
|
143
|
-
</Section>
|
|
144
|
-
</div>
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
export const TypographyTokens = () => (
|
|
148
|
-
<div className="space-y-3 max-w-md">
|
|
149
|
-
<p className="text-foreground text-sm font-medium">text-foreground — primary body</p>
|
|
150
|
-
<p className="text-muted-foreground text-sm">text-muted-foreground — secondary / hints</p>
|
|
151
|
-
<p className="text-primary text-sm">text-primary — brand links / accents</p>
|
|
152
|
-
<p className="text-destructive text-sm">text-destructive — error messages</p>
|
|
153
|
-
<p className="text-warning text-sm">text-warning — warning labels</p>
|
|
154
|
-
<p className="text-success text-sm">text-success — success labels</p>
|
|
155
|
-
<p className="text-info text-sm">text-info — info labels</p>
|
|
156
|
-
</div>
|
|
157
|
-
);
|