@opensaas/stack-ui 0.1.0
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/.turbo/turbo-build.log +8 -0
- package/README.md +286 -0
- package/dist/components/AdminUI.d.ts +24 -0
- package/dist/components/AdminUI.d.ts.map +1 -0
- package/dist/components/AdminUI.js +48 -0
- package/dist/components/ConfirmDialog.d.ts +16 -0
- package/dist/components/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/ConfirmDialog.js +11 -0
- package/dist/components/Dashboard.d.ts +12 -0
- package/dist/components/Dashboard.d.ts.map +1 -0
- package/dist/components/Dashboard.js +30 -0
- package/dist/components/ItemForm.d.ts +17 -0
- package/dist/components/ItemForm.d.ts.map +1 -0
- package/dist/components/ItemForm.js +97 -0
- package/dist/components/ItemFormClient.d.ts +22 -0
- package/dist/components/ItemFormClient.d.ts.map +1 -0
- package/dist/components/ItemFormClient.js +127 -0
- package/dist/components/ListView.d.ts +17 -0
- package/dist/components/ListView.d.ts.map +1 -0
- package/dist/components/ListView.js +76 -0
- package/dist/components/ListViewClient.d.ts +19 -0
- package/dist/components/ListViewClient.d.ts.map +1 -0
- package/dist/components/ListViewClient.js +108 -0
- package/dist/components/LoadingSpinner.d.ts +10 -0
- package/dist/components/LoadingSpinner.d.ts.map +1 -0
- package/dist/components/LoadingSpinner.js +14 -0
- package/dist/components/Navigation.d.ts +13 -0
- package/dist/components/Navigation.d.ts.map +1 -0
- package/dist/components/Navigation.js +20 -0
- package/dist/components/SkeletonLoader.d.ts +22 -0
- package/dist/components/SkeletonLoader.d.ts.map +1 -0
- package/dist/components/SkeletonLoader.js +25 -0
- package/dist/components/fields/CheckboxField.d.ts +11 -0
- package/dist/components/fields/CheckboxField.d.ts.map +1 -0
- package/dist/components/fields/CheckboxField.js +10 -0
- package/dist/components/fields/ComboboxField.d.ts +18 -0
- package/dist/components/fields/ComboboxField.d.ts.map +1 -0
- package/dist/components/fields/ComboboxField.js +32 -0
- package/dist/components/fields/FieldRenderer.d.ts +22 -0
- package/dist/components/fields/FieldRenderer.d.ts.map +1 -0
- package/dist/components/fields/FieldRenderer.js +81 -0
- package/dist/components/fields/IntegerField.d.ts +15 -0
- package/dist/components/fields/IntegerField.d.ts.map +1 -0
- package/dist/components/fields/IntegerField.js +14 -0
- package/dist/components/fields/PasswordField.d.ts +18 -0
- package/dist/components/fields/PasswordField.d.ts.map +1 -0
- package/dist/components/fields/PasswordField.js +42 -0
- package/dist/components/fields/RelationshipField.d.ts +20 -0
- package/dist/components/fields/RelationshipField.d.ts.map +1 -0
- package/dist/components/fields/RelationshipField.js +11 -0
- package/dist/components/fields/RelationshipManager.d.ts +19 -0
- package/dist/components/fields/RelationshipManager.d.ts.map +1 -0
- package/dist/components/fields/RelationshipManager.js +37 -0
- package/dist/components/fields/SelectField.d.ts +16 -0
- package/dist/components/fields/SelectField.d.ts.map +1 -0
- package/dist/components/fields/SelectField.js +11 -0
- package/dist/components/fields/TextField.d.ts +13 -0
- package/dist/components/fields/TextField.d.ts.map +1 -0
- package/dist/components/fields/TextField.js +11 -0
- package/dist/components/fields/TimestampField.d.ts +12 -0
- package/dist/components/fields/TimestampField.d.ts.map +1 -0
- package/dist/components/fields/TimestampField.js +12 -0
- package/dist/components/fields/index.d.ts +23 -0
- package/dist/components/fields/index.d.ts.map +1 -0
- package/dist/components/fields/index.js +13 -0
- package/dist/components/fields/registry.d.ts +43 -0
- package/dist/components/fields/registry.d.ts.map +1 -0
- package/dist/components/fields/registry.js +42 -0
- package/dist/components/standalone/DeleteButton.d.ts +35 -0
- package/dist/components/standalone/DeleteButton.d.ts.map +1 -0
- package/dist/components/standalone/DeleteButton.js +46 -0
- package/dist/components/standalone/ItemCreateForm.d.ts +34 -0
- package/dist/components/standalone/ItemCreateForm.d.ts.map +1 -0
- package/dist/components/standalone/ItemCreateForm.js +91 -0
- package/dist/components/standalone/ItemEditForm.d.ts +37 -0
- package/dist/components/standalone/ItemEditForm.d.ts.map +1 -0
- package/dist/components/standalone/ItemEditForm.js +112 -0
- package/dist/components/standalone/ListTable.d.ts +33 -0
- package/dist/components/standalone/ListTable.d.ts.map +1 -0
- package/dist/components/standalone/ListTable.js +94 -0
- package/dist/components/standalone/SearchBar.d.ts +29 -0
- package/dist/components/standalone/SearchBar.d.ts.map +1 -0
- package/dist/components/standalone/SearchBar.js +43 -0
- package/dist/components/standalone/index.d.ts +11 -0
- package/dist/components/standalone/index.d.ts.map +1 -0
- package/dist/components/standalone/index.js +6 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/lib/serializeFieldConfig.d.ts +43 -0
- package/dist/lib/serializeFieldConfig.d.ts.map +1 -0
- package/dist/lib/serializeFieldConfig.js +48 -0
- package/dist/lib/theme.d.ts +17 -0
- package/dist/lib/theme.d.ts.map +1 -0
- package/dist/lib/theme.js +192 -0
- package/dist/lib/utils.d.ts +18 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +76 -0
- package/dist/primitives/button.d.ts +12 -0
- package/dist/primitives/button.d.ts.map +1 -0
- package/dist/primitives/button.js +33 -0
- package/dist/primitives/calendar.d.ts +9 -0
- package/dist/primitives/calendar.d.ts.map +1 -0
- package/dist/primitives/calendar.js +48 -0
- package/dist/primitives/card.d.ts +9 -0
- package/dist/primitives/card.d.ts.map +1 -0
- package/dist/primitives/card.js +16 -0
- package/dist/primitives/checkbox.d.ts +5 -0
- package/dist/primitives/checkbox.d.ts.map +1 -0
- package/dist/primitives/checkbox.js +7 -0
- package/dist/primitives/combobox.d.ts +14 -0
- package/dist/primitives/combobox.d.ts.map +1 -0
- package/dist/primitives/combobox.js +20 -0
- package/dist/primitives/datetime-picker.d.ts +9 -0
- package/dist/primitives/datetime-picker.d.ts.map +1 -0
- package/dist/primitives/datetime-picker.js +42 -0
- package/dist/primitives/dialog.d.ts +20 -0
- package/dist/primitives/dialog.d.ts.map +1 -0
- package/dist/primitives/dialog.js +21 -0
- package/dist/primitives/index.d.ts +14 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +14 -0
- package/dist/primitives/input.d.ts +5 -0
- package/dist/primitives/input.d.ts.map +1 -0
- package/dist/primitives/input.js +8 -0
- package/dist/primitives/label.d.ts +6 -0
- package/dist/primitives/label.d.ts.map +1 -0
- package/dist/primitives/label.js +9 -0
- package/dist/primitives/popover.d.ts +7 -0
- package/dist/primitives/popover.d.ts.map +1 -0
- package/dist/primitives/popover.js +10 -0
- package/dist/primitives/select.d.ts +14 -0
- package/dist/primitives/select.d.ts.map +1 -0
- package/dist/primitives/select.js +24 -0
- package/dist/primitives/table.d.ts +11 -0
- package/dist/primitives/table.d.ts.map +1 -0
- package/dist/primitives/table.js +20 -0
- package/dist/primitives/time-picker.d.ts +8 -0
- package/dist/primitives/time-picker.d.ts.map +1 -0
- package/dist/primitives/time-picker.js +27 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +2 -0
- package/dist/server/types.d.ts +15 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +1 -0
- package/dist/styles/globals.css +1896 -0
- package/package.json +91 -0
- package/postcss.config.cjs +5 -0
- package/src/components/AdminUI.tsx +112 -0
- package/src/components/ConfirmDialog.tsx +56 -0
- package/src/components/Dashboard.tsx +134 -0
- package/src/components/ItemForm.tsx +195 -0
- package/src/components/ItemFormClient.tsx +237 -0
- package/src/components/ListView.tsx +153 -0
- package/src/components/ListViewClient.tsx +282 -0
- package/src/components/LoadingSpinner.tsx +32 -0
- package/src/components/Navigation.tsx +117 -0
- package/src/components/SkeletonLoader.tsx +82 -0
- package/src/components/fields/CheckboxField.tsx +54 -0
- package/src/components/fields/ComboboxField.tsx +127 -0
- package/src/components/fields/FieldRenderer.tsx +132 -0
- package/src/components/fields/IntegerField.tsx +68 -0
- package/src/components/fields/PasswordField.tsx +159 -0
- package/src/components/fields/RelationshipField.tsx +71 -0
- package/src/components/fields/RelationshipManager.tsx +189 -0
- package/src/components/fields/SelectField.tsx +71 -0
- package/src/components/fields/TextField.tsx +59 -0
- package/src/components/fields/TimestampField.tsx +49 -0
- package/src/components/fields/index.ts +27 -0
- package/src/components/fields/registry.ts +72 -0
- package/src/components/standalone/DeleteButton.tsx +114 -0
- package/src/components/standalone/ItemCreateForm.tsx +161 -0
- package/src/components/standalone/ItemEditForm.tsx +193 -0
- package/src/components/standalone/ListTable.tsx +211 -0
- package/src/components/standalone/SearchBar.tsx +86 -0
- package/src/components/standalone/index.ts +13 -0
- package/src/index.ts +74 -0
- package/src/lib/serializeFieldConfig.ts +88 -0
- package/src/lib/theme.ts +202 -0
- package/src/lib/utils.ts +81 -0
- package/src/primitives/button.tsx +49 -0
- package/src/primitives/calendar.tsx +160 -0
- package/src/primitives/card.tsx +58 -0
- package/src/primitives/checkbox.tsx +27 -0
- package/src/primitives/combobox.tsx +159 -0
- package/src/primitives/datetime-picker.tsx +130 -0
- package/src/primitives/dialog.tsx +108 -0
- package/src/primitives/index.ts +54 -0
- package/src/primitives/input.tsx +24 -0
- package/src/primitives/label.tsx +19 -0
- package/src/primitives/popover.tsx +31 -0
- package/src/primitives/select.tsx +158 -0
- package/src/primitives/table.tsx +91 -0
- package/src/primitives/time-picker.tsx +65 -0
- package/src/server/index.ts +3 -0
- package/src/server/types.ts +15 -0
- package/src/styles/globals.css +123 -0
- package/tailwind.config.ts +3 -0
- package/tests/components/TextField.test.tsx +94 -0
- package/tests/setup.ts +11 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +22 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract only serializable properties from a single field config
|
|
3
|
+
* Removes functions (getZodSchema, getPrismaType, getTypeScriptType)
|
|
4
|
+
* and non-serializable properties (access, hooks, typePatch, valueForClientSerialization)
|
|
5
|
+
*/
|
|
6
|
+
export function serializeFieldConfig(fieldConfig) {
|
|
7
|
+
const config = {
|
|
8
|
+
type: fieldConfig.type,
|
|
9
|
+
};
|
|
10
|
+
// Process ui options, excluding the valueForClientSerialization function
|
|
11
|
+
if (fieldConfig.ui) {
|
|
12
|
+
const { valueForClientSerialization: _valueForClientSerialization, ...serializableUi } = fieldConfig.ui;
|
|
13
|
+
config.ui = serializableUi;
|
|
14
|
+
}
|
|
15
|
+
// Extract label if present
|
|
16
|
+
if ('label' in fieldConfig && fieldConfig.label !== undefined) {
|
|
17
|
+
config.label = fieldConfig.label;
|
|
18
|
+
}
|
|
19
|
+
// Extract validation if present
|
|
20
|
+
if ('validation' in fieldConfig && fieldConfig.validation !== undefined) {
|
|
21
|
+
config.validation = fieldConfig.validation;
|
|
22
|
+
}
|
|
23
|
+
// Extract options for select fields
|
|
24
|
+
if ('options' in fieldConfig && fieldConfig.options !== undefined) {
|
|
25
|
+
config.options = fieldConfig.options;
|
|
26
|
+
}
|
|
27
|
+
// Extract many for relationship fields
|
|
28
|
+
if ('many' in fieldConfig && fieldConfig.many !== undefined) {
|
|
29
|
+
config.many = fieldConfig.many;
|
|
30
|
+
}
|
|
31
|
+
// Extract ref for relationship fields
|
|
32
|
+
if ('ref' in fieldConfig && fieldConfig.ref !== undefined) {
|
|
33
|
+
config.ref = fieldConfig.ref;
|
|
34
|
+
}
|
|
35
|
+
return config;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract only serializable properties from field configs
|
|
39
|
+
* Removes functions (getZodSchema, getPrismaType, getTypeScriptType)
|
|
40
|
+
* and non-serializable properties (access, hooks, typePatch)
|
|
41
|
+
*/
|
|
42
|
+
export function serializeFieldConfigs(fields) {
|
|
43
|
+
const serialized = {};
|
|
44
|
+
for (const [fieldName, fieldConfig] of Object.entries(fields)) {
|
|
45
|
+
serialized[fieldName] = serializeFieldConfig(fieldConfig);
|
|
46
|
+
}
|
|
47
|
+
return serialized;
|
|
48
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ThemeColors, ThemeConfig, ThemePreset } from '@opensaas/stack-core';
|
|
2
|
+
/**
|
|
3
|
+
* Preset theme definitions
|
|
4
|
+
*/
|
|
5
|
+
export declare const presetThemes: Record<ThemePreset, {
|
|
6
|
+
light: ThemeColors;
|
|
7
|
+
dark: ThemeColors;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Generate CSS variables from theme configuration
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateThemeCSS(config?: ThemeConfig): string;
|
|
13
|
+
/**
|
|
14
|
+
* Get theme CSS as a style tag content
|
|
15
|
+
*/
|
|
16
|
+
export declare function getThemeStyleTag(config?: ThemeConfig): string;
|
|
17
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEjF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAiJvF,CAAA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAuC7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset theme definitions
|
|
3
|
+
*/
|
|
4
|
+
export const presetThemes = {
|
|
5
|
+
modern: {
|
|
6
|
+
light: {
|
|
7
|
+
background: '220 20% 97%',
|
|
8
|
+
foreground: '220 30% 10%',
|
|
9
|
+
card: '0 0% 100%',
|
|
10
|
+
cardForeground: '220 30% 10%',
|
|
11
|
+
popover: '0 0% 100%',
|
|
12
|
+
popoverForeground: '220 30% 10%',
|
|
13
|
+
primary: '190 95% 55%',
|
|
14
|
+
primaryForeground: '220 30% 10%',
|
|
15
|
+
secondary: '220 15% 94%',
|
|
16
|
+
secondaryForeground: '220 30% 10%',
|
|
17
|
+
muted: '220 15% 94%',
|
|
18
|
+
mutedForeground: '220 15% 45%',
|
|
19
|
+
accent: '280 85% 65%',
|
|
20
|
+
accentForeground: '0 0% 100%',
|
|
21
|
+
destructive: '0 84% 60%',
|
|
22
|
+
destructiveForeground: '0 0% 100%',
|
|
23
|
+
border: '220 15% 88%',
|
|
24
|
+
input: '220 15% 88%',
|
|
25
|
+
ring: '190 95% 55%',
|
|
26
|
+
gradientFrom: '190 95% 55%',
|
|
27
|
+
gradientTo: '280 85% 65%',
|
|
28
|
+
},
|
|
29
|
+
dark: {
|
|
30
|
+
background: '220 25% 8%',
|
|
31
|
+
foreground: '220 15% 95%',
|
|
32
|
+
card: '220 20% 12%',
|
|
33
|
+
cardForeground: '220 15% 95%',
|
|
34
|
+
popover: '220 20% 12%',
|
|
35
|
+
popoverForeground: '220 15% 95%',
|
|
36
|
+
primary: '190 100% 60%',
|
|
37
|
+
primaryForeground: '220 30% 10%',
|
|
38
|
+
secondary: '220 20% 18%',
|
|
39
|
+
secondaryForeground: '220 15% 95%',
|
|
40
|
+
muted: '220 20% 18%',
|
|
41
|
+
mutedForeground: '220 10% 55%',
|
|
42
|
+
accent: '280 90% 70%',
|
|
43
|
+
accentForeground: '220 30% 10%',
|
|
44
|
+
destructive: '0 84% 65%',
|
|
45
|
+
destructiveForeground: '0 0% 100%',
|
|
46
|
+
border: '220 20% 22%',
|
|
47
|
+
input: '220 20% 22%',
|
|
48
|
+
ring: '190 100% 60%',
|
|
49
|
+
gradientFrom: '190 100% 60%',
|
|
50
|
+
gradientTo: '280 90% 70%',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
classic: {
|
|
54
|
+
light: {
|
|
55
|
+
background: '0 0% 100%',
|
|
56
|
+
foreground: '222.2 84% 4.9%',
|
|
57
|
+
card: '0 0% 100%',
|
|
58
|
+
cardForeground: '222.2 84% 4.9%',
|
|
59
|
+
popover: '0 0% 100%',
|
|
60
|
+
popoverForeground: '222.2 84% 4.9%',
|
|
61
|
+
primary: '221.2 83.2% 53.3%',
|
|
62
|
+
primaryForeground: '210 40% 98%',
|
|
63
|
+
secondary: '210 40% 96.1%',
|
|
64
|
+
secondaryForeground: '222.2 47.4% 11.2%',
|
|
65
|
+
muted: '210 40% 96.1%',
|
|
66
|
+
mutedForeground: '215.4 16.3% 46.9%',
|
|
67
|
+
accent: '210 40% 96.1%',
|
|
68
|
+
accentForeground: '222.2 47.4% 11.2%',
|
|
69
|
+
destructive: '0 84.2% 60.2%',
|
|
70
|
+
destructiveForeground: '210 40% 98%',
|
|
71
|
+
border: '214.3 31.8% 91.4%',
|
|
72
|
+
input: '214.3 31.8% 91.4%',
|
|
73
|
+
ring: '221.2 83.2% 53.3%',
|
|
74
|
+
gradientFrom: '221.2 83.2% 53.3%',
|
|
75
|
+
gradientTo: '221.2 83.2% 53.3%',
|
|
76
|
+
},
|
|
77
|
+
dark: {
|
|
78
|
+
background: '222.2 84% 4.9%',
|
|
79
|
+
foreground: '210 40% 98%',
|
|
80
|
+
card: '222.2 84% 8%',
|
|
81
|
+
cardForeground: '210 40% 98%',
|
|
82
|
+
popover: '222.2 84% 8%',
|
|
83
|
+
popoverForeground: '210 40% 98%',
|
|
84
|
+
primary: '221.2 83.2% 53.3%',
|
|
85
|
+
primaryForeground: '210 40% 98%',
|
|
86
|
+
secondary: '217.2 32.6% 17.5%',
|
|
87
|
+
secondaryForeground: '210 40% 98%',
|
|
88
|
+
muted: '217.2 32.6% 17.5%',
|
|
89
|
+
mutedForeground: '215 20.2% 65.1%',
|
|
90
|
+
accent: '217.2 32.6% 17.5%',
|
|
91
|
+
accentForeground: '210 40% 98%',
|
|
92
|
+
destructive: '0 84.2% 60.2%',
|
|
93
|
+
destructiveForeground: '210 40% 98%',
|
|
94
|
+
border: '217.2 32.6% 17.5%',
|
|
95
|
+
input: '217.2 32.6% 17.5%',
|
|
96
|
+
ring: '221.2 83.2% 53.3%',
|
|
97
|
+
gradientFrom: '221.2 83.2% 53.3%',
|
|
98
|
+
gradientTo: '221.2 83.2% 53.3%',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
neon: {
|
|
102
|
+
light: {
|
|
103
|
+
background: '0 0% 100%',
|
|
104
|
+
foreground: '240 10% 5%',
|
|
105
|
+
card: '0 0% 100%',
|
|
106
|
+
cardForeground: '240 10% 5%',
|
|
107
|
+
popover: '0 0% 100%',
|
|
108
|
+
popoverForeground: '240 10% 5%',
|
|
109
|
+
primary: '330 100% 50%',
|
|
110
|
+
primaryForeground: '0 0% 100%',
|
|
111
|
+
secondary: '240 5% 96%',
|
|
112
|
+
secondaryForeground: '240 10% 5%',
|
|
113
|
+
muted: '240 5% 96%',
|
|
114
|
+
mutedForeground: '240 5% 45%',
|
|
115
|
+
accent: '155 100% 50%',
|
|
116
|
+
accentForeground: '240 10% 5%',
|
|
117
|
+
destructive: '0 100% 50%',
|
|
118
|
+
destructiveForeground: '0 0% 100%',
|
|
119
|
+
border: '240 5.9% 90%',
|
|
120
|
+
input: '240 5.9% 90%',
|
|
121
|
+
ring: '330 100% 50%',
|
|
122
|
+
gradientFrom: '330 100% 50%',
|
|
123
|
+
gradientTo: '155 100% 50%',
|
|
124
|
+
},
|
|
125
|
+
dark: {
|
|
126
|
+
background: '240 10% 5%',
|
|
127
|
+
foreground: '0 0% 98%',
|
|
128
|
+
card: '240 10% 8%',
|
|
129
|
+
cardForeground: '0 0% 98%',
|
|
130
|
+
popover: '240 10% 8%',
|
|
131
|
+
popoverForeground: '0 0% 98%',
|
|
132
|
+
primary: '330 100% 60%',
|
|
133
|
+
primaryForeground: '240 10% 5%',
|
|
134
|
+
secondary: '240 5% 15%',
|
|
135
|
+
secondaryForeground: '0 0% 98%',
|
|
136
|
+
muted: '240 5% 15%',
|
|
137
|
+
mutedForeground: '240 5% 60%',
|
|
138
|
+
accent: '155 100% 60%',
|
|
139
|
+
accentForeground: '240 10% 5%',
|
|
140
|
+
destructive: '0 100% 60%',
|
|
141
|
+
destructiveForeground: '0 0% 100%',
|
|
142
|
+
border: '240 5% 20%',
|
|
143
|
+
input: '240 5% 20%',
|
|
144
|
+
ring: '330 100% 60%',
|
|
145
|
+
gradientFrom: '330 100% 60%',
|
|
146
|
+
gradientTo: '155 100% 60%',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Generate CSS variables from theme configuration
|
|
152
|
+
*/
|
|
153
|
+
export function generateThemeCSS(config) {
|
|
154
|
+
const preset = config?.preset || 'modern';
|
|
155
|
+
const radius = config?.radius ?? 0.75;
|
|
156
|
+
// Get base colors from preset
|
|
157
|
+
const baseLight = presetThemes[preset].light;
|
|
158
|
+
const baseDark = presetThemes[preset].dark;
|
|
159
|
+
// Merge with custom overrides
|
|
160
|
+
const lightColors = { ...baseLight, ...config?.colors };
|
|
161
|
+
const darkColors = { ...baseDark, ...config?.darkColors };
|
|
162
|
+
// Convert colors to CSS variables
|
|
163
|
+
const colorToCSSVar = (key, value) => {
|
|
164
|
+
// Convert camelCase to kebab-case with --color- prefix
|
|
165
|
+
const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
166
|
+
return ` --color-${cssKey}: ${value};`;
|
|
167
|
+
};
|
|
168
|
+
const lightVars = Object.entries(lightColors)
|
|
169
|
+
.map(([key, value]) => colorToCSSVar(key, value))
|
|
170
|
+
.join('\n');
|
|
171
|
+
const darkVars = Object.entries(darkColors)
|
|
172
|
+
.map(([key, value]) => colorToCSSVar(key, value))
|
|
173
|
+
.join('\n');
|
|
174
|
+
return `
|
|
175
|
+
:root {
|
|
176
|
+
${lightVars}
|
|
177
|
+
--radius: ${radius}rem;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@media (prefers-color-scheme: dark) {
|
|
181
|
+
:root {
|
|
182
|
+
${darkVars}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
`.trim();
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get theme CSS as a style tag content
|
|
189
|
+
*/
|
|
190
|
+
export function getThemeStyleTag(config) {
|
|
191
|
+
return `<style id="opensaas-theme">${generateThemeCSS(config)}</style>`;
|
|
192
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ClassValue } from 'clsx';
|
|
2
|
+
/**
|
|
3
|
+
* Merge Tailwind CSS classes with clsx
|
|
4
|
+
*/
|
|
5
|
+
export declare function cn(...inputs: ClassValue[]): string;
|
|
6
|
+
/**
|
|
7
|
+
* Format a list name for display (PascalCase → Title Case)
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatListName(name: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Format a field name for display (camelCase → Title Case)
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatFieldName(name: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get the display value for a field
|
|
16
|
+
*/
|
|
17
|
+
export declare function getFieldDisplayValue(value: unknown, fieldType: string): string;
|
|
18
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C;;GAEG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAiB9E"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
/**
|
|
4
|
+
* Merge Tailwind CSS classes with clsx
|
|
5
|
+
*/
|
|
6
|
+
export function cn(...inputs) {
|
|
7
|
+
return twMerge(clsx(inputs));
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Format a list name for display (PascalCase → Title Case)
|
|
11
|
+
*/
|
|
12
|
+
export function formatListName(name) {
|
|
13
|
+
return name
|
|
14
|
+
.replace(/([A-Z])/g, ' $1')
|
|
15
|
+
.trim()
|
|
16
|
+
.replace(/^./, (str) => str.toUpperCase());
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format a field name for display (camelCase → Title Case)
|
|
20
|
+
*/
|
|
21
|
+
export function formatFieldName(name) {
|
|
22
|
+
return name
|
|
23
|
+
.replace(/([A-Z])/g, ' $1')
|
|
24
|
+
.replace(/^./, (str) => str.toUpperCase())
|
|
25
|
+
.trim();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the display value for a field
|
|
29
|
+
*/
|
|
30
|
+
export function getFieldDisplayValue(value, fieldType) {
|
|
31
|
+
if (value === null || value === undefined) {
|
|
32
|
+
return '-';
|
|
33
|
+
}
|
|
34
|
+
switch (fieldType) {
|
|
35
|
+
case 'checkbox':
|
|
36
|
+
return value ? 'Yes' : 'No';
|
|
37
|
+
case 'timestamp':
|
|
38
|
+
return new Date(value).toLocaleString();
|
|
39
|
+
case 'password':
|
|
40
|
+
return '••••••••';
|
|
41
|
+
case 'relationship':
|
|
42
|
+
return getRelationshipDisplayValue(value);
|
|
43
|
+
default:
|
|
44
|
+
return String(value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get display value for a relationship field
|
|
49
|
+
* Tries to display: name → title → label → id
|
|
50
|
+
*/
|
|
51
|
+
function getRelationshipDisplayValue(value) {
|
|
52
|
+
if (!value || typeof value !== 'object') {
|
|
53
|
+
return '-';
|
|
54
|
+
}
|
|
55
|
+
// Handle array of relationships (many: true)
|
|
56
|
+
if (Array.isArray(value)) {
|
|
57
|
+
if (value.length === 0)
|
|
58
|
+
return '-';
|
|
59
|
+
return value.map((item) => getRelationshipDisplayValue(item)).join(', ');
|
|
60
|
+
}
|
|
61
|
+
// Handle single relationship object
|
|
62
|
+
let displayValue;
|
|
63
|
+
if ('name' in value) {
|
|
64
|
+
displayValue = value.name;
|
|
65
|
+
}
|
|
66
|
+
else if ('title' in value) {
|
|
67
|
+
displayValue = value.title;
|
|
68
|
+
}
|
|
69
|
+
else if ('label' in value) {
|
|
70
|
+
displayValue = value.label;
|
|
71
|
+
}
|
|
72
|
+
else if ('id' in value) {
|
|
73
|
+
displayValue = value.id;
|
|
74
|
+
}
|
|
75
|
+
return displayValue ? String(displayValue) : '-';
|
|
76
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
export { Button, buttonVariants };
|
|
12
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/primitives/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,QAAA,MAAM,cAAc;;;8EAwBnB,CAAA;AAED,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EACnD,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,QAAA,MAAM,MAAM,uFAOX,CAAA;AAGD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { cn } from '../lib/utils.js';
|
|
6
|
+
const buttonVariants = cva('inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', {
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
10
|
+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
11
|
+
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
12
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
13
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
14
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
default: 'h-10 px-4 py-2',
|
|
18
|
+
sm: 'h-9 rounded-md px-3',
|
|
19
|
+
lg: 'h-11 rounded-md px-8',
|
|
20
|
+
icon: 'h-10 w-10',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: 'default',
|
|
25
|
+
size: 'default',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
29
|
+
const Comp = asChild ? Slot : 'button';
|
|
30
|
+
return (_jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref: ref, ...props }));
|
|
31
|
+
});
|
|
32
|
+
Button.displayName = 'Button';
|
|
33
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface CalendarProps {
|
|
2
|
+
selected?: Date;
|
|
3
|
+
onSelect?: (date: Date) => void;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
mode?: 'single';
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function Calendar({ selected, onSelect, disabled, className }: CalendarProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=calendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/primitives/calendar.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,IAAI,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,aAAa,2CAoIlF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { format, addMonths, subMonths, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, isSameMonth, isSameDay, isToday, } from 'date-fns';
|
|
5
|
+
import { cn } from '../lib/utils.js';
|
|
6
|
+
import { Button } from './button.js';
|
|
7
|
+
export function Calendar({ selected, onSelect, disabled, className }) {
|
|
8
|
+
const [currentMonth, setCurrentMonth] = React.useState(selected || new Date());
|
|
9
|
+
const monthStart = startOfMonth(currentMonth);
|
|
10
|
+
const monthEnd = endOfMonth(monthStart);
|
|
11
|
+
const startDate = startOfWeek(monthStart);
|
|
12
|
+
const endDate = endOfWeek(monthEnd);
|
|
13
|
+
const handlePrevMonth = () => {
|
|
14
|
+
setCurrentMonth(subMonths(currentMonth, 1));
|
|
15
|
+
};
|
|
16
|
+
const handleNextMonth = () => {
|
|
17
|
+
setCurrentMonth(addMonths(currentMonth, 1));
|
|
18
|
+
};
|
|
19
|
+
const handleToday = () => {
|
|
20
|
+
const today = new Date();
|
|
21
|
+
setCurrentMonth(today);
|
|
22
|
+
if (onSelect) {
|
|
23
|
+
onSelect(today);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const rows = [];
|
|
27
|
+
let days = [];
|
|
28
|
+
let day = startDate;
|
|
29
|
+
while (day <= endDate) {
|
|
30
|
+
for (let i = 0; i < 7; i++) {
|
|
31
|
+
days.push(day);
|
|
32
|
+
day = addDays(day, 1);
|
|
33
|
+
}
|
|
34
|
+
rows.push(days);
|
|
35
|
+
days = [];
|
|
36
|
+
}
|
|
37
|
+
return (_jsxs("div", { className: cn('p-3', className), children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsx(Button, { variant: "outline", size: "icon", onClick: handlePrevMonth, disabled: disabled, type: "button", className: "h-8 w-8", children: _jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-sm font-semibold", children: format(currentMonth, 'MMMM yyyy') }), _jsx(Button, { variant: "ghost", size: "sm", onClick: handleToday, disabled: disabled, type: "button", className: "h-7 text-xs", children: "Today" })] }), _jsx(Button, { variant: "outline", size: "icon", onClick: handleNextMonth, disabled: disabled, type: "button", className: "h-8 w-8", children: _jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) })] }), _jsxs("table", { className: "w-full border-collapse", children: [_jsx("thead", { children: _jsx("tr", { children: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'].map((day) => (_jsx("th", { className: "text-muted-foreground text-xs font-normal h-9 w-9 p-0", children: day }, day))) }) }), _jsx("tbody", { children: rows.map((week, weekIdx) => (_jsx("tr", { children: week.map((day, dayIdx) => {
|
|
38
|
+
const isSelected = selected && isSameDay(day, selected);
|
|
39
|
+
const isCurrentMonth = isSameMonth(day, currentMonth);
|
|
40
|
+
const isDayToday = isToday(day);
|
|
41
|
+
return (_jsx("td", { className: "p-0 text-center", children: _jsx(Button, { variant: "ghost", type: "button", onClick: () => {
|
|
42
|
+
if (onSelect && !disabled) {
|
|
43
|
+
onSelect(day);
|
|
44
|
+
}
|
|
45
|
+
}, disabled: disabled, className: cn('h-9 w-9 p-0 font-normal hover:bg-accent', !isCurrentMonth && 'text-muted-foreground opacity-50', isSelected &&
|
|
46
|
+
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground', isDayToday && !isSelected && 'bg-accent'), children: format(day, 'd') }) }, dayIdx));
|
|
47
|
+
}) }, weekIdx))) })] })] }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
3
|
+
declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
4
|
+
declare const CardTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
5
|
+
declare const CardDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
declare const CardContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
declare const CardFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
|
9
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/primitives/card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,QAAA,MAAM,IAAI,6GAWT,CAAA;AAGD,QAAA,MAAM,UAAU,6GAIf,CAAA;AAGD,QAAA,MAAM,SAAS,6GAQd,CAAA;AAGD,QAAA,MAAM,eAAe,6GAIpB,CAAA;AAGD,QAAA,MAAM,WAAW,6GAIhB,CAAA;AAGD,QAAA,MAAM,UAAU,6GAIf,CAAA;AAGD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cn } from '../lib/utils.js';
|
|
4
|
+
const Card = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('rounded-lg border border-border bg-card text-card-foreground shadow-sm', className), ...props })));
|
|
5
|
+
Card.displayName = 'Card';
|
|
6
|
+
const CardHeader = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('flex flex-col space-y-1.5 p-6', className), ...props })));
|
|
7
|
+
CardHeader.displayName = 'CardHeader';
|
|
8
|
+
const CardTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('text-2xl font-semibold leading-none tracking-tight', className), ...props })));
|
|
9
|
+
CardTitle.displayName = 'CardTitle';
|
|
10
|
+
const CardDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('text-sm text-muted-foreground', className), ...props })));
|
|
11
|
+
CardDescription.displayName = 'CardDescription';
|
|
12
|
+
const CardContent = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('p-6 pt-0', className), ...props })));
|
|
13
|
+
CardContent.displayName = 'CardContent';
|
|
14
|
+
const CardFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('flex items-center p-6 pt-0', className), ...props })));
|
|
15
|
+
CardFooter.displayName = 'CardFooter';
|
|
16
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
3
|
+
declare const Checkbox: React.ForwardRefExoticComponent<Omit<CheckboxPrimitive.CheckboxProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
4
|
+
export { Checkbox };
|
|
5
|
+
//# sourceMappingURL=checkbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/primitives/checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAI7D,QAAA,MAAM,QAAQ,iKAkBZ,CAAA;AAGF,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
4
|
+
import { cn } from '../lib/utils.js';
|
|
5
|
+
const Checkbox = React.forwardRef(({ className, ...props }, ref) => (_jsx(CheckboxPrimitive.Root, { ref: ref, className: cn('peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground', className), ...props, children: _jsx(CheckboxPrimitive.Indicator, { className: cn('flex items-center justify-center text-current'), children: _jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }) })));
|
|
6
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
7
|
+
export { Checkbox };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
3
|
+
declare const Combobox: React.FC<PopoverPrimitive.PopoverProps>;
|
|
4
|
+
declare const ComboboxTrigger: React.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
5
|
+
declare const ComboboxContent: React.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
declare const ComboboxSearch: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & React.RefAttributes<HTMLInputElement>>;
|
|
7
|
+
declare const ComboboxList: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
declare const ComboboxEmpty: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
+
declare const ComboboxItem: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
10
|
+
selected?: boolean;
|
|
11
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
+
declare const ComboboxSeparator: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
export { Combobox, ComboboxTrigger, ComboboxContent, ComboboxSearch, ComboboxList, ComboboxEmpty, ComboboxItem, ComboboxSeparator, };
|
|
14
|
+
//# sourceMappingURL=combobox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/primitives/combobox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAG3D,QAAA,MAAM,QAAQ,yCAAwB,CAAA;AAEtC,QAAA,MAAM,eAAe,sKA2BnB,CAAA;AAGF,QAAA,MAAM,eAAe,gKAoBnB,CAAA;AAGF,QAAA,MAAM,cAAc,sHA2BlB,CAAA;AAGF,QAAA,MAAM,YAAY,6GAUjB,CAAA;AAGD,QAAA,MAAM,aAAa,6GAUlB,CAAA;AAGD,QAAA,MAAM,YAAY;eAEoC,OAAO;wCAsB3D,CAAA;AAGF,QAAA,MAAM,iBAAiB,6GAItB,CAAA;AAGD,OAAO,EACL,QAAQ,EACR,eAAe,EACf,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,iBAAiB,GAClB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
4
|
+
import { cn } from '../lib/utils.js';
|
|
5
|
+
const Combobox = PopoverPrimitive.Root;
|
|
6
|
+
const ComboboxTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(PopoverPrimitive.Trigger, { ref: ref, className: cn('flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: [children, _jsx("svg", { className: "ml-2 h-4 w-4 shrink-0 opacity-50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 9l4-4 4 4m0 6l-4 4-4-4" }) })] })));
|
|
7
|
+
ComboboxTrigger.displayName = PopoverPrimitive.Trigger.displayName;
|
|
8
|
+
const ComboboxContent = React.forwardRef(({ className, children, align = 'start', sideOffset = 4, ...props }, ref) => (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { ref: ref, align: align, sideOffset: sideOffset, className: cn('z-50 w-full min-w-[var(--radix-popover-trigger-width)] rounded-md border border-border bg-popover p-0 text-popover-foreground shadow-md outline-none', 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95', 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', className), ...props, children: children }) })));
|
|
9
|
+
ComboboxContent.displayName = PopoverPrimitive.Content.displayName;
|
|
10
|
+
const ComboboxSearch = React.forwardRef(({ className, ...props }, ref) => (_jsxs("div", { className: "flex items-center border-b border-border px-3", children: [_jsx("svg", { className: "mr-2 h-4 w-4 shrink-0 opacity-50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), _jsx("input", { ref: ref, className: cn('flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50', className), ...props })] })));
|
|
11
|
+
ComboboxSearch.displayName = 'ComboboxSearch';
|
|
12
|
+
const ComboboxList = React.forwardRef(({ className, children, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className), ...props, children: children })));
|
|
13
|
+
ComboboxList.displayName = 'ComboboxList';
|
|
14
|
+
const ComboboxEmpty = React.forwardRef(({ className, children = 'No results found.', ...props }, ref) => (_jsx("div", { ref: ref, className: cn('py-6 text-center text-sm text-muted-foreground', className), ...props, children: children })));
|
|
15
|
+
ComboboxEmpty.displayName = 'ComboboxEmpty';
|
|
16
|
+
const ComboboxItem = React.forwardRef(({ className, children, selected, ...props }, ref) => (_jsxs("div", { ref: ref, className: cn('relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none', 'hover:bg-accent hover:text-accent-foreground', 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50', selected && 'bg-accent text-accent-foreground', className), ...props, children: [selected && (_jsx("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) })), children] })));
|
|
17
|
+
ComboboxItem.displayName = 'ComboboxItem';
|
|
18
|
+
const ComboboxSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('-mx-1 my-1 h-px bg-border', className), ...props })));
|
|
19
|
+
ComboboxSeparator.displayName = 'ComboboxSeparator';
|
|
20
|
+
export { Combobox, ComboboxTrigger, ComboboxContent, ComboboxSearch, ComboboxList, ComboboxEmpty, ComboboxItem, ComboboxSeparator, };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface DateTimePickerProps {
|
|
2
|
+
value?: Date | null;
|
|
3
|
+
onChange?: (date: Date | null) => void;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
className?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function DateTimePicker({ value, onChange, disabled, className, placeholder, }: DateTimePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=datetime-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datetime-picker.d.ts","sourceRoot":"","sources":["../../src/primitives/datetime-picker.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAA;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAoC,GACrC,EAAE,mBAAmB,2CAyGrB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { format } from 'date-fns';
|
|
5
|
+
import { cn } from '../lib/utils.js';
|
|
6
|
+
import { Button } from './button.js';
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
8
|
+
import { Calendar } from './calendar.js';
|
|
9
|
+
import { TimePicker } from './time-picker.js';
|
|
10
|
+
export function DateTimePicker({ value, onChange, disabled, className, placeholder = 'Pick a date and time', }) {
|
|
11
|
+
const [open, setOpen] = React.useState(false);
|
|
12
|
+
const [selectedDate, setSelectedDate] = React.useState(value || undefined);
|
|
13
|
+
const handleDateSelect = (date) => {
|
|
14
|
+
// Preserve time if we already have a selected date
|
|
15
|
+
if (selectedDate) {
|
|
16
|
+
date.setHours(selectedDate.getHours());
|
|
17
|
+
date.setMinutes(selectedDate.getMinutes());
|
|
18
|
+
}
|
|
19
|
+
setSelectedDate(date);
|
|
20
|
+
};
|
|
21
|
+
const handleTimeChange = (date) => {
|
|
22
|
+
setSelectedDate(date);
|
|
23
|
+
};
|
|
24
|
+
const handleConfirm = () => {
|
|
25
|
+
if (onChange) {
|
|
26
|
+
onChange(selectedDate || null);
|
|
27
|
+
}
|
|
28
|
+
setOpen(false);
|
|
29
|
+
};
|
|
30
|
+
const handleCancel = () => {
|
|
31
|
+
setSelectedDate(value || undefined);
|
|
32
|
+
setOpen(false);
|
|
33
|
+
};
|
|
34
|
+
const handleClear = () => {
|
|
35
|
+
setSelectedDate(undefined);
|
|
36
|
+
if (onChange) {
|
|
37
|
+
onChange(null);
|
|
38
|
+
}
|
|
39
|
+
setOpen(false);
|
|
40
|
+
};
|
|
41
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", type: "button", disabled: disabled, className: cn('w-full justify-start text-left font-normal', !value && 'text-muted-foreground', className), children: [_jsx("svg", { className: "mr-2 h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }), value ? format(value, 'dd/MM/yyyy, h:mm a') : _jsx("span", { children: placeholder })] }) }), _jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: _jsxs("div", { className: "p-4 space-y-4", children: [_jsx(Calendar, { selected: selectedDate, onSelect: handleDateSelect, disabled: disabled }), _jsxs("div", { className: "border-t pt-4", children: [_jsx("div", { className: "text-sm font-medium mb-2", children: "Time" }), _jsx(TimePicker, { value: selectedDate, onChange: handleTimeChange, disabled: disabled })] }), _jsxs("div", { className: "flex gap-2 border-t pt-4", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: handleClear, disabled: disabled, type: "button", className: "flex-1", children: "Clear" }), _jsx(Button, { variant: "outline", size: "sm", onClick: handleCancel, disabled: disabled, type: "button", className: "flex-1", children: "Cancel" }), _jsx(Button, { size: "sm", onClick: handleConfirm, disabled: disabled, type: "button", className: "flex-1", children: "Confirm" })] })] }) })] }));
|
|
42
|
+
}
|