@cryptlex/web-components 5.2.0 → 5.3.0-alpha01

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/components/data-table/data-table-filter.d.ts +27 -0
  2. package/dist/components/data-table/data-table-filter.js +2 -0
  3. package/dist/components/data-table/data-table-filter.js.map +1 -0
  4. package/dist/components/data-table/data-table.d.ts +72 -0
  5. package/dist/components/data-table/data-table.js +2 -0
  6. package/dist/components/data-table/data-table.js.map +1 -0
  7. package/dist/components/data-table/table-commons.d.ts +56 -0
  8. package/dist/components/data-table/table-commons.js +2 -0
  9. package/dist/components/data-table/table-commons.js.map +1 -0
  10. package/dist/components/inputs/checkbox.d.ts +8 -0
  11. package/dist/components/inputs/checkbox.js +2 -0
  12. package/dist/components/inputs/checkbox.js.map +1 -0
  13. package/dist/components/inputs/date-picker.d.ts +11 -0
  14. package/dist/components/inputs/date-picker.js +2 -0
  15. package/dist/components/inputs/date-picker.js.map +1 -0
  16. package/dist/components/inputs/datefield.d.ts +14 -0
  17. package/dist/components/inputs/datefield.js +2 -0
  18. package/dist/components/inputs/datefield.js.map +1 -0
  19. package/dist/components/inputs/field.d.ts +20 -0
  20. package/dist/components/inputs/field.js +2 -0
  21. package/dist/components/inputs/field.js.map +1 -0
  22. package/dist/components/inputs/id-search.d.ts +20 -0
  23. package/dist/components/inputs/id-search.js +2 -0
  24. package/dist/components/inputs/id-search.js.map +1 -0
  25. package/dist/components/inputs/input-otp.d.ts +7 -0
  26. package/dist/components/inputs/input-otp.js +2 -0
  27. package/dist/components/inputs/input-otp.js.map +1 -0
  28. package/dist/components/inputs/multi-select.d.ts +16 -0
  29. package/dist/components/inputs/multi-select.js +2 -0
  30. package/dist/components/inputs/multi-select.js.map +1 -0
  31. package/dist/components/inputs/numberfield.d.ts +6 -0
  32. package/dist/components/inputs/numberfield.js +2 -0
  33. package/dist/components/inputs/numberfield.js.map +1 -0
  34. package/dist/components/inputs/searchfield.d.ts +5 -0
  35. package/dist/components/inputs/searchfield.js +2 -0
  36. package/dist/components/inputs/searchfield.js.map +1 -0
  37. package/dist/components/inputs/select-options.d.ts +8 -0
  38. package/dist/components/inputs/select-options.js +2 -0
  39. package/dist/components/inputs/select-options.js.map +1 -0
  40. package/dist/components/inputs/select.d.ts +17 -0
  41. package/dist/components/inputs/select.js +2 -0
  42. package/dist/components/inputs/select.js.map +1 -0
  43. package/dist/components/inputs/textfield.d.ts +7 -0
  44. package/dist/components/inputs/textfield.js +2 -0
  45. package/dist/components/inputs/textfield.js.map +1 -0
  46. package/dist/components/key-value-card/key-value-card.d.ts +17 -0
  47. package/dist/components/key-value-card/key-value-card.js +2 -0
  48. package/dist/components/key-value-card/key-value-card.js.map +1 -0
  49. package/dist/components/ui/alert.d.ts +8 -0
  50. package/dist/components/ui/alert.js +2 -0
  51. package/dist/components/ui/alert.js.map +1 -0
  52. package/dist/components/ui/avatar.d.ts +7 -0
  53. package/dist/components/ui/avatar.js +2 -0
  54. package/dist/components/ui/avatar.js.map +1 -0
  55. package/dist/components/ui/badge.d.ts +1 -0
  56. package/dist/components/ui/badge.js +2 -0
  57. package/dist/components/ui/badge.js.map +1 -0
  58. package/dist/components/ui/breadcrumbs.d.ts +10 -0
  59. package/dist/components/ui/breadcrumbs.js +2 -0
  60. package/dist/components/ui/breadcrumbs.js.map +1 -0
  61. package/dist/components/ui/button.d.ts +11 -0
  62. package/dist/components/ui/button.js +2 -0
  63. package/dist/components/ui/button.js.map +1 -0
  64. package/dist/components/ui/calendar.d.ts +16 -0
  65. package/dist/components/ui/calendar.js +2 -0
  66. package/dist/components/ui/calendar.js.map +1 -0
  67. package/dist/components/ui/card.d.ts +7 -0
  68. package/dist/components/ui/card.js +2 -0
  69. package/dist/components/ui/card.js.map +1 -0
  70. package/dist/components/ui/dialog.d.ts +18 -0
  71. package/dist/components/ui/dialog.js +2 -0
  72. package/dist/components/ui/dialog.js.map +1 -0
  73. package/dist/components/ui/disclosure.d.ts +18 -0
  74. package/dist/components/ui/disclosure.js +2 -0
  75. package/dist/components/ui/disclosure.js.map +1 -0
  76. package/dist/components/ui/list-box.d.ts +5 -0
  77. package/dist/components/ui/list-box.js +2 -0
  78. package/dist/components/ui/list-box.js.map +1 -0
  79. package/dist/components/ui/loader.d.ts +5 -0
  80. package/dist/components/ui/loader.js +2 -0
  81. package/dist/components/ui/loader.js.map +1 -0
  82. package/dist/components/ui/menu.d.ts +24 -0
  83. package/dist/components/ui/menu.js +2 -0
  84. package/dist/components/ui/menu.js.map +1 -0
  85. package/dist/components/ui/popover.d.ts +4 -0
  86. package/dist/components/ui/popover.js +2 -0
  87. package/dist/components/ui/popover.js.map +1 -0
  88. package/dist/components/ui/sidebar.d.ts +52 -0
  89. package/dist/components/ui/sidebar.js +2 -0
  90. package/dist/components/ui/sidebar.js.map +1 -0
  91. package/dist/components/ui/skeleton.d.ts +1 -0
  92. package/dist/components/ui/skeleton.js +2 -0
  93. package/dist/components/ui/skeleton.js.map +1 -0
  94. package/dist/components/ui/sonner.d.ts +4 -0
  95. package/dist/components/ui/sonner.js +2 -0
  96. package/dist/components/ui/sonner.js.map +1 -0
  97. package/dist/components/ui/table.d.ts +8 -0
  98. package/dist/components/ui/table.js +2 -0
  99. package/dist/components/ui/table.js.map +1 -0
  100. package/dist/components/ui/tabs.d.ts +5 -0
  101. package/dist/components/ui/tabs.js +2 -0
  102. package/dist/components/ui/tabs.js.map +1 -0
  103. package/dist/components/ui/timeline.d.ts +15 -0
  104. package/dist/components/ui/timeline.js +2 -0
  105. package/dist/components/ui/timeline.js.map +1 -0
  106. package/dist/components/ui/tooltip.d.ts +4 -0
  107. package/dist/components/ui/tooltip.js +2 -0
  108. package/dist/components/ui/tooltip.js.map +1 -0
  109. package/dist/utils/form-context.d.ts +4 -0
  110. package/dist/utils/form-context.js +2 -0
  111. package/dist/utils/form-context.js.map +1 -0
  112. package/dist/utils/form-hook.d.ts +23 -0
  113. package/dist/utils/form-hook.js +2 -0
  114. package/dist/utils/form-hook.js.map +1 -0
  115. package/dist/utils/primitives.d.ts +44 -0
  116. package/dist/utils/primitives.js +2 -0
  117. package/dist/utils/primitives.js.map +1 -0
  118. package/dist/utils/resource-names.d.ts +11 -0
  119. package/dist/utils/resource-names.js +2 -0
  120. package/dist/utils/resource-names.js.map +1 -0
  121. package/dist/utils/use-mobile.d.ts +1 -0
  122. package/dist/utils/use-mobile.js +2 -0
  123. package/dist/utils/use-mobile.js.map +1 -0
  124. package/package.json +16 -8
  125. package/lib/components/data-table/data-table-filter.tsx +0 -220
  126. package/lib/components/data-table/data-table.tsx +0 -593
  127. package/lib/components/data-table/table-commons.tsx +0 -233
  128. package/lib/components/inputs/checkbox.tsx +0 -72
  129. package/lib/components/inputs/date-picker.tsx +0 -130
  130. package/lib/components/inputs/datefield.tsx +0 -109
  131. package/lib/components/inputs/field.tsx +0 -106
  132. package/lib/components/inputs/id-search.tsx +0 -83
  133. package/lib/components/inputs/input-otp.tsx +0 -63
  134. package/lib/components/inputs/multi-select.tsx +0 -62
  135. package/lib/components/inputs/numberfield.tsx +0 -110
  136. package/lib/components/inputs/searchfield.tsx +0 -87
  137. package/lib/components/inputs/select-options.tsx +0 -303
  138. package/lib/components/inputs/select.tsx +0 -140
  139. package/lib/components/inputs/textfield.tsx +0 -96
  140. package/lib/components/key-value-card/key-value-card.tsx +0 -115
  141. package/lib/components/ui/alert.tsx +0 -32
  142. package/lib/components/ui/avatar.tsx +0 -22
  143. package/lib/components/ui/badge.tsx +0 -19
  144. package/lib/components/ui/breadcrumbs.tsx +0 -104
  145. package/lib/components/ui/button.tsx +0 -66
  146. package/lib/components/ui/calendar.tsx +0 -220
  147. package/lib/components/ui/card.tsx +0 -58
  148. package/lib/components/ui/dialog.tsx +0 -172
  149. package/lib/components/ui/disclosure.tsx +0 -113
  150. package/lib/components/ui/list-box.tsx +0 -86
  151. package/lib/components/ui/loader.tsx +0 -10
  152. package/lib/components/ui/menu.tsx +0 -168
  153. package/lib/components/ui/popover.tsx +0 -37
  154. package/lib/components/ui/sidebar.tsx +0 -552
  155. package/lib/components/ui/skeleton.tsx +0 -7
  156. package/lib/components/ui/sonner.tsx +0 -26
  157. package/lib/components/ui/table.tsx +0 -79
  158. package/lib/components/ui/tabs.tsx +0 -82
  159. package/lib/components/ui/timeline.tsx +0 -52
  160. package/lib/components/ui/tooltip.tsx +0 -30
  161. package/lib/tokens.scss +0 -89
  162. package/lib/utils/form-context.tsx +0 -7
  163. package/lib/utils/form-hook.tsx +0 -33
  164. package/lib/utils/primitives.ts +0 -68
  165. package/lib/utils/resource-names.tsx +0 -245
  166. package/lib/utils/use-mobile.tsx +0 -21
@@ -1,233 +0,0 @@
1
-
2
- import type { components, operations, paths } from "@cryptlex/web-api-types";
3
- import type { PaginationState, SortingState, Table } from "@tanstack/react-table";
4
- import { createColumnHelper } from "@tanstack/react-table";
5
- import { intervalToDuration } from "date-fns";
6
- import { Checkbox } from "lib/components/inputs/checkbox";
7
- import type { LucideIcon } from "lucide-react";
8
- import type createClient from "openapi-fetch";
9
- import type { PressEvent } from "react-aria-components";
10
-
11
- const cH = createColumnHelper<any>();
12
- export const TABLE_CHECK_BOX_COLUMN = [
13
- cH.accessor("checkbox", {
14
- header: ({ table }) => (
15
- <Checkbox
16
- isIndeterminate={table.getIsSomeRowsSelected() && !table.getIsAllPageRowsSelected()}
17
- isSelected={
18
- table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected()
19
- }
20
- onChange={() => table.toggleAllPageRowsSelected()}
21
- aria-label="Select all"
22
- />
23
- ),
24
-
25
- cell: ({ row }) => (
26
- <Checkbox
27
- isSelected={row.getIsSelected()}
28
- onChange={() => row.toggleSelected()}
29
- aria-label="Select row"
30
- />
31
- ),
32
- enableSorting: false,
33
- enableHiding: false,
34
- }),
35
- ];
36
-
37
- export const TABLE_ID_COLUMN = [
38
- cH.accessor("id", {
39
- header: () => "ID",
40
- }),
41
- ];
42
- export const TABLE_DEFAULT_DATE_COLUMNS = [
43
- cH.accessor("createdAt", {
44
- header: () => "Creation Date",
45
- cell: ({ row }) => {
46
- const date = row.getValue("createdAt") satisfies
47
- | string
48
- | null
49
- | undefined;
50
- return formatDate(date);
51
- },
52
- enableHiding: false,
53
- }),
54
- cH.accessor("updatedAt", {
55
- header: () => "Last Updated",
56
- cell: ({ row }) => {
57
- const date = row.getValue("updatedAt") satisfies
58
- | string
59
- | null
60
- | undefined;
61
- return formatDate(date);
62
- },
63
- enableHiding: false,
64
- }),
65
- ];
66
-
67
- // TODO, i18n
68
- export function formatDate(date: string | null | undefined) {
69
- if (!date) return null;
70
- const _date = new Date(date);
71
- return new Intl.DateTimeFormat(undefined, {
72
- dateStyle: "medium",
73
- timeStyle: "short",
74
- }).format(_date);
75
- }
76
- /**
77
- * Format multiple license parameters (expired, suspended, revoked) into a single status
78
- */
79
- export function getLicenseStatus(license: any): string {
80
- const licenseExpired =
81
- license.expiresAt && new Date(license.expiresAt) < new Date();
82
- // Status Column
83
- switch (true) {
84
- case license.revoked && license.suspended && licenseExpired:
85
- return "Revoked, Suspended, Expired";
86
- case license.revoked && license.suspended:
87
- return "Revoked, Suspended";
88
- case license.revoked && licenseExpired:
89
- return "Revoked, Expired";
90
- case license.suspended && licenseExpired:
91
- return "Suspended, Expired";
92
- case license.suspended:
93
- return "Suspended";
94
- case license.revoked:
95
- return "Revoked";
96
- case licenseExpired:
97
- return "Expired";
98
- default:
99
- return "Active";
100
- }
101
- }
102
-
103
- export function getValidityDisplay(validity: number | undefined) {
104
- if (validity === 0 || !validity) {
105
- return "Lifetime";
106
- } else {
107
- return secondsToDuration(validity);
108
- }
109
- }
110
- export function secondsToDuration(seconds: number): string {
111
- //@ts-ignore
112
- const duration = intervalToDuration({
113
- start: 0,
114
- end: seconds * 1000,
115
- });
116
-
117
- const parts = [
118
- duration.years && `${duration.years}y`,
119
- duration.months && `${duration.months}m`,
120
- duration.days && `${duration.days}d`,
121
- duration.hours && `${duration.hours}h`,
122
- ];
123
-
124
- // Filter out undefined values and join
125
- return parts.filter(Boolean).join(" ").trim();
126
- }
127
-
128
- export function getValueFromData(
129
- data: any,
130
- accessor: string | number | symbol,
131
- ) {
132
- const accessors = accessor.toString().split(".");
133
- let value = data;
134
- for (const acc of accessors) {
135
- value = value?.[acc];
136
- }
137
- return value;
138
- }
139
- export const ALL_OS: { [key: string]: string } = {
140
- windows: "Windows",
141
- macos: "macOS",
142
- linux: "Linux",
143
- ios: "iOS",
144
- android: "Android",
145
- };
146
-
147
- export type VisibilityState<T> = {
148
- [K in keyof T]?: boolean;
149
- };
150
-
151
- export type TableActions = ({
152
- onClick: (e: PressEvent, t: Table<any>) => void
153
- bulk: boolean;
154
- icon: LucideIcon
155
- tooltip?: string;
156
- })[]
157
-
158
- export type TableFetchFn<TData, TOperation extends keyof operations> = (
159
- p: PaginationState,
160
- s: SortingState,
161
- q: string,
162
- f: ApiFilters<TOperation>
163
- ) => Promise<{
164
- total: number;
165
- data: TData[] | undefined;
166
- }>;
167
- /*** Type for hide some of the columns based on the dto of the particular page
168
- ** `id`, `updatedAt` are by default hidden
169
- */
170
- export type DefaultVisibilityState<T> = {
171
- [K in keyof T]?: boolean;
172
- };
173
-
174
-
175
- type Client = ReturnType<typeof createClient<paths>>;
176
-
177
- // Helper type to extract valid GET paths
178
- type GetPaths = {
179
- [P in keyof paths]: paths[P] extends { get: any } ? P : never;
180
- }[keyof paths];
181
-
182
- export type ApiSchema<T extends keyof components['schemas']> = components['schemas'][T];
183
- export type ApiQuery<T extends keyof operations> = NonNullable<operations[T]['parameters']['query']>;
184
- export type ApiGetAllParameters = {
185
- page: number;
186
- limit: number;
187
- search?: string;
188
- sort?: string;
189
- }
190
-
191
-
192
- export type ApiFilter<T extends keyof operations> = Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>
193
- export type ApiFilters<T extends keyof operations> = NonNullable<Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>>
194
-
195
- export function createTableFetchFn<Return, Operation extends keyof operations>(
196
- ctxclient: Client,
197
- path: GetPaths,
198
- ): TableFetchFn<Return, Operation> {
199
- return async (pagination, sorting, searching, filters) => {
200
- const query: ApiQuery<Operation> = {
201
- ...filters,
202
- page: pagination.pageIndex + 1,
203
- limit: pagination.pageSize,
204
- sort: generateSortParam(sorting[0]),
205
- search: searching,
206
- };
207
-
208
- // const pathParams = merge(_baseQueryObject, params);
209
-
210
- return ctxclient.GET(path, { query }).then((value) => {
211
- const rowCount = Number.parseInt(
212
- value.response.headers.get("Pagination-Count") || "0",
213
- );
214
- return { total: rowCount, data: value.data };
215
- });
216
- };
217
- }
218
-
219
- function generateSortParam(
220
- sort: { id: string; desc: boolean } | undefined,
221
- ): string {
222
- if (sort) {
223
- if (sort.desc) {
224
- return `-${sort.id}`;
225
- } else {
226
- return `+${sort.id}`;
227
- }
228
- } else {
229
- return "-createdAt";
230
- }
231
- }
232
-
233
-
@@ -1,72 +0,0 @@
1
- import {
2
- Checkbox as AriaCheckbox,
3
- CheckboxGroup as AriaCheckboxGroup,
4
- composeRenderProps,
5
- type CheckboxProps as AriaCheckboxProps
6
- } from "react-aria-components";
7
-
8
- import { FormField, labelVariants, type FormFieldProps } from "lib/components/inputs/field";
9
- import { useFieldContext } from "lib/utils/form-context";
10
- import { cn } from "lib/utils/primitives";
11
- import { Check, Minus } from "lucide-react";
12
-
13
- export const CheckboxGroup = AriaCheckboxGroup
14
- type CheckboxProps = AriaCheckboxProps & FormFieldProps;
15
- export function Checkbox({ className, label, description, errorMessage, ...props }: Omit<CheckboxProps, 'children'>) {
16
- return (
17
- <div className="group form-field">
18
- <FormField label={label} description={description} errorMessage={errorMessage}>
19
- <AriaCheckbox
20
- className={composeRenderProps(className, (className) =>
21
- cn(
22
- "group/checkbox cursor-pointer focus-ring flex items-center gap-x-2",
23
- /* Disabled */
24
- "disabled-muted",
25
- labelVariants,
26
- className
27
- )
28
- )}
29
- {...props}
30
- >
31
- {composeRenderProps(<></>, (_, renderProps) => (
32
- <>
33
- <div
34
- className={cn(
35
- "flex size-input shrink-0 items-center bg-card justify-center border border-input text-current ring-offset-background",
36
- /* Selected */
37
- "group-data-[indeterminate]/checkbox:bg-primary group-data-[selected]/checkbox:bg-primary group-data-[indeterminate]/checkbox:text-primary-foreground group-data-[selected]/checkbox:text-primary-foreground",
38
- /* Disabled */
39
- "group-data-[disabled]/checkbox:cursor-not-allowed group-data-[disabled]/checkbox:opacity-50",
40
- /* Invalid */
41
- "group-data-[invalid]/checkbox:border-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-destructive-foreground",
42
- /* Resets */
43
- "focus:outline-none focus-visible:outline-none"
44
- )}
45
- >
46
- {renderProps.isIndeterminate ? (
47
- <Minus className="size-icon" />
48
- ) : renderProps.isSelected ? (
49
- <Check className="size-icon" />
50
- ) : null}
51
- </div>
52
- </>
53
- ))}
54
- </AriaCheckbox>
55
- </FormField>
56
- </div>
57
- )
58
- }
59
-
60
- export type TfCheckboxProps = Omit<React.ComponentProps<typeof Checkbox>, "onChange" | "onBlur" | "isChecked">
61
- export function TfCheckbox({ ...props }: TfCheckboxProps) {
62
- const field = useFieldContext<boolean>();
63
- return (
64
- <Checkbox
65
- isSelected={field.state.value}
66
- isDisabled={field.form.state.isSubmitting || props.isDisabled}
67
- onChange={() => field.handleChange(!field.state.value)}
68
- onBlur={field.handleBlur}
69
- {...props}
70
- />
71
- );
72
- };
@@ -1,130 +0,0 @@
1
- import { CalendarIcon } from "lucide-react"
2
- import {
3
- DatePicker as AriaDatePicker,
4
- DatePickerProps as AriaDatePickerProps,
5
- DateRangePicker as AriaDateRangePicker,
6
- DateRangePickerProps as AriaDateRangePickerProps,
7
- DateValue as AriaDateValue,
8
- Dialog as AriaDialog,
9
- DialogProps as AriaDialogProps,
10
- PopoverProps as AriaPopoverProps,
11
- composeRenderProps,
12
- Popover
13
- } from "react-aria-components"
14
-
15
- import { getLocalTimeZone, parseAbsolute, type ZonedDateTime } from "@internationalized/date"
16
- import { DateInput } from "lib/components/inputs/datefield"
17
- import { FieldGroup, FormField, type FormFieldProps } from "lib/components/inputs/field"
18
- import { Button } from "lib/components/ui/button"
19
- import { Calendar, RangeCalendar } from "lib/components/ui/calendar"
20
- import { useFieldContext } from "lib/utils/form-context"
21
- import { getFieldErrorMessage } from "lib/utils/form-hook"
22
- import { cn } from "lib/utils/primitives"
23
-
24
- const DatePickerContent = ({
25
- className,
26
- popoverClassName,
27
- ...props
28
- }: AriaDialogProps & { popoverClassName?: AriaPopoverProps["className"] }) => (
29
- <Popover
30
- className={composeRenderProps(popoverClassName, (className) =>
31
- cn("w-auto p-3", className)
32
- )}
33
- >
34
- <AriaDialog
35
- className={cn(
36
- "flex w-full flex-col gap-y-2 outline-none sm:flex-row sm:gap-x-icon sm:gap-y-0",
37
- className
38
- )}
39
- {...props}
40
- />
41
- </Popover>
42
- )
43
-
44
- interface DatePickerProps<T extends AriaDateValue> extends AriaDatePickerProps<T>, FormFieldProps { }
45
-
46
- export function DatePicker<T extends AriaDateValue>({
47
- label,
48
- description,
49
- errorMessage,
50
- className,
51
- ...props
52
- }: DatePickerProps<T>) {
53
- return (
54
- <AriaDatePicker
55
- className={composeRenderProps(className, (className) =>
56
- cn("group flex flex-col gap-2", className)
57
- )}
58
- {...props}
59
- >
60
- <FormField label={label} description={description} errorMessage={errorMessage}>
61
- <FieldGroup aria-label={label}>
62
- <DateInput className="flex-1" variant="ghost" />
63
- <Button
64
- variant="ghost"
65
- size="icon"
66
- className={'-me-2 ms-2'}
67
- >
68
- <CalendarIcon aria-hidden />
69
- </Button>
70
- </FieldGroup>
71
- </FormField>
72
- <DatePickerContent>
73
- <Calendar />
74
- </DatePickerContent>
75
- </AriaDatePicker>
76
- )
77
- }
78
-
79
- export function TfDatePicker({ ...props }: Omit<DatePickerProps<ZonedDateTime>, 'value' | 'onChange' | 'onBlur' | 'isInvalid' | 'errorMessage'>) {
80
- const field = useFieldContext<string | null>();
81
- return (
82
- <DatePicker
83
- hideTimeZone
84
- value={field.state.value ? parseAbsolute(field.state.value, getLocalTimeZone()) : null}
85
- onChange={(v) => v ? field.handleChange(v.toAbsoluteString()) : field.handleChange(null)}
86
- onBlur={field.handleBlur}
87
- isInvalid={!!getFieldErrorMessage(field)}
88
- errorMessage={getFieldErrorMessage(field)}
89
- {...props}
90
- />)
91
- }
92
-
93
- interface DateRangePickerProps<T extends AriaDateValue> extends AriaDateRangePickerProps<T>, FormFieldProps { }
94
- export function DateRangePicker<T extends AriaDateValue>({
95
- label,
96
- description,
97
- errorMessage,
98
- className,
99
- ...props
100
- }: DateRangePickerProps<T>) {
101
- return (
102
- <AriaDateRangePicker
103
- className={composeRenderProps(className, (className) =>
104
- cn("group flex flex-col gap-2", className)
105
- )}
106
- {...props}
107
- >
108
- <FormField label={label} errorMessage={errorMessage} description={description}>
109
- <FieldGroup>
110
- <DateInput variant="ghost" slot={"start"} />
111
- <span aria-hidden className="px-2 text-sm text-muted-foreground">
112
- -
113
- </span>
114
- <DateInput className="flex-1" variant="ghost" slot={"end"} />
115
- <Button
116
- variant="ghost"
117
- size="icon"
118
- className="mr-1 data-[focus-visible]:ring-offset-0"
119
- >
120
- <CalendarIcon aria-hidden />
121
- </Button>
122
- </FieldGroup>
123
- </FormField>
124
- <DatePickerContent>
125
- <RangeCalendar />
126
- </DatePickerContent>
127
- </AriaDateRangePicker>
128
- )
129
- }
130
-
@@ -1,109 +0,0 @@
1
- "use client"
2
-
3
- import { VariantProps } from "class-variance-authority"
4
- import {
5
- DateField as AriaDateField,
6
- DateFieldProps as AriaDateFieldProps,
7
- DateInput as AriaDateInput,
8
- DateInputProps as AriaDateInputProps,
9
- DateSegment as AriaDateSegment,
10
- DateSegmentProps as AriaDateSegmentProps,
11
- DateValue as AriaDateValue,
12
- TimeField as AriaTimeField,
13
- TimeFieldProps as AriaTimeFieldProps,
14
- TimeValue as AriaTimeValue,
15
- composeRenderProps
16
- } from "react-aria-components"
17
-
18
-
19
- import { cn } from "lib/utils/primitives"
20
- import { fieldGroupVariants, FormField, type FormFieldProps } from "./field"
21
-
22
- export function DateSegment({ className, ...props }: AriaDateSegmentProps) {
23
- return (
24
- <AriaDateSegment
25
- className={composeRenderProps(className, (className) =>
26
- cn(
27
- "inline caret-transparent outline-0",
28
- /* Placeholder */
29
- "data-[placeholder]:text-muted-foreground",
30
- /* Disabled */
31
- "disabled-muted",
32
- /* Focused */
33
- "data-[focused]:bg-accent data-[focused]:text-accent-foreground",
34
- /* Invalid */
35
- "data-[invalid]:data-[focused]:bg-destructive data-[invalid]:data-[focused]:data-[placeholder]:text-destructive-foreground data-[invalid]:data-[focused]:text-destructive-foreground data-[invalid]:data-[placeholder]:text-destructive data-[invalid]:text-destructive",
36
- className
37
- )
38
- )}
39
- {...props}
40
- />
41
- )
42
- }
43
-
44
- interface DateInputProps
45
- extends AriaDateInputProps,
46
- VariantProps<typeof fieldGroupVariants> { }
47
-
48
- export function DateInput({
49
- className,
50
- variant,
51
- ...props
52
- }: Omit<DateInputProps, "children">) {
53
- return (
54
- <AriaDateInput
55
- className={composeRenderProps(className, (className) =>
56
- cn(fieldGroupVariants({ variant }), "text-sm", className)
57
- )}
58
- {...props}
59
- >
60
- {(segment) => <DateSegment segment={segment} />}
61
- </AriaDateInput>
62
- )
63
- }
64
-
65
- interface DateFieldProps<T extends AriaDateValue> extends AriaDateFieldProps<T>, FormFieldProps { }
66
-
67
- export function DateField<T extends AriaDateValue>({
68
- label,
69
- description,
70
- className,
71
- errorMessage,
72
- ...props
73
- }: DateFieldProps<T>) {
74
- return (
75
- <AriaDateField
76
- className={composeRenderProps(className, (className) =>
77
- cn("group form-field", className)
78
- )}
79
- {...props}
80
- >
81
- <FormField label={label} description={description} errorMessage={errorMessage}>
82
- <DateInput />
83
- </FormField>
84
- </AriaDateField>
85
- )
86
- }
87
-
88
- interface TimeFieldProps<T extends AriaTimeValue> extends AriaTimeFieldProps<T>, FormFieldProps { }
89
-
90
- export function TimeField<T extends AriaTimeValue>({
91
- label,
92
- description,
93
- errorMessage,
94
- className,
95
- ...props
96
- }: TimeFieldProps<T>) {
97
- return (
98
- <AriaTimeField
99
- className={composeRenderProps(className, (className) =>
100
- cn("group form-field", className)
101
- )}
102
- {...props}
103
- >
104
- <FormField label={label} description={description} errorMessage={errorMessage}>
105
- <DateInput />
106
- </FormField>
107
- </AriaTimeField>
108
- )
109
- }
@@ -1,106 +0,0 @@
1
- "use client"
2
-
3
- import { cva, type VariantProps } from "class-variance-authority"
4
- import {
5
- Group as AriaGroup,
6
- GroupProps as AriaGroupProps,
7
- Label as AriaLabel,
8
- LabelProps as AriaLabelProps,
9
- Text as AriaText,
10
- TextProps as AriaTextProps,
11
- composeRenderProps
12
- } from "react-aria-components"
13
-
14
- import { cn } from "lib/utils/primitives"
15
- import { CircleX, Info } from "lucide-react"
16
- import type React from "react"
17
-
18
- export const labelVariants = cva([
19
- "select-none text-sm font-medium leading-none",
20
- /* Disabled */
21
- "disabled-muted",
22
- /* Invalid */
23
- "group-data-[invalid]:text-destructive",
24
- ])
25
-
26
- export function FieldLabel({ className, ...props }: AriaLabelProps) {
27
- return (
28
- <AriaLabel className={cn(labelVariants(), className)} {...props} />
29
- )
30
- }
31
-
32
- export function FieldDescription({ className, children, ...props }: AriaTextProps) {
33
- return (
34
- <AriaText
35
- className={cn("text-sm text-muted leading-tight", className)}
36
- {...props}
37
- slot="description"
38
- >
39
- {children}<Info className="inline size-2 align-text-top ms-0.5" />
40
- </AriaText>
41
- )
42
- }
43
- // TODO, if we were to use AriaFieldError, it would use the internal ValidationState Context object, which might be useful for composing inputs but
44
- // this would have significant overlap with what Tanstack Form is already doing for us. It has pros and cons, needs to be discussed and explored.
45
- export function FieldError({ className, children, ...props }: React.ComponentPropsWithRef<'div'>) {
46
- return (
47
- <div
48
- className={cn("text-sm leading-tight text-destructive duration-150 animate-in transition-transform slide-in-from-top-5 fade-in", className)}
49
- {...props}
50
- >
51
- {children}<CircleX className="inline size-2 align-text-top ms-0.5" />
52
- </div>
53
- )
54
- }
55
-
56
- export const fieldGroupVariants = cva("", {
57
- variants: {
58
- variant: {
59
- default: [
60
- // TODO standardize the padding here
61
- "relative flex h-input w-full items-center overflow-hidden border border-input bg-card px-2 py-2 text-sm ring-offset-background",
62
- /* Focus Within */
63
- "focus-ring",
64
- /* Disabled */
65
- "disabled-muted",
66
- ],
67
- ghost: "",
68
- },
69
- },
70
- defaultVariants: {
71
- variant: "default",
72
- },
73
- })
74
-
75
- export interface GroupProps
76
- extends AriaGroupProps,
77
- VariantProps<typeof fieldGroupVariants> { }
78
-
79
- export function FieldGroup({ className, variant, ...props }: GroupProps) {
80
- return (
81
- <AriaGroup
82
- className={composeRenderProps(className, (className) =>
83
- cn(fieldGroupVariants({ variant }), className)
84
- )}
85
- {...props}
86
- />
87
- )
88
- }
89
-
90
- export type FormFieldProps = {
91
- label?: string
92
- description?: React.ReactNode
93
- errorMessage?: string
94
- // | ((validation: AriaValidationResult) => string)
95
- }
96
-
97
- export function FormField({ label, description, errorMessage, children }: FormFieldProps & {
98
- children: React.ReactNode
99
- }) {
100
- return <>
101
- {label && <FieldLabel>{label}</FieldLabel>}
102
- {children}
103
- {description && (<FieldDescription>{description}</FieldDescription>)}
104
- {errorMessage && <FieldError>{errorMessage}</FieldError>}
105
- </>
106
- }