torch-glare 2.5.3 → 2.5.5
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/apps/lib/components/ActionButton.tsx +39 -6
- package/apps/lib/components/Badge.tsx +5 -2
- package/apps/lib/components/BadgeField.tsx +71 -67
- package/apps/lib/components/Button.tsx +4 -4
- package/apps/lib/components/Calendar.tsx +7 -17
- package/apps/lib/components/Card.tsx +2 -1
- package/apps/lib/components/ColorPicker.tsx +1 -1
- package/apps/lib/components/ContextMenu.tsx +65 -22
- package/apps/lib/components/DataViews/context.ts +2 -2
- package/apps/lib/components/DataViews/data-views.tsx +3 -3
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -2
- package/apps/lib/components/DataViews/views/table-view.tsx +190 -153
- package/apps/lib/components/Drawer.tsx +18 -1
- package/apps/lib/components/DropdownMenu.tsx +65 -22
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +19 -5
- package/apps/lib/components/FormBuilder/types.ts +16 -0
- package/apps/lib/components/FormRenderer/form-renderer.tsx +16 -5
- package/apps/lib/components/FormRenderer/stepper.tsx +22 -16
- package/apps/lib/components/HeaderBar.tsx +51 -53
- package/apps/lib/components/Input.tsx +19 -4
- package/apps/lib/components/InputField.tsx +46 -47
- package/apps/lib/components/Popover.tsx +108 -56
- package/apps/lib/components/SearchableSelect.tsx +22 -17
- package/apps/lib/components/SearchableTree.tsx +33 -17
- package/apps/lib/components/SearchableTreeDialog.tsx +21 -12
- package/apps/lib/components/SectionBlock.tsx +3 -1
- package/apps/lib/components/Select.tsx +86 -54
- package/apps/lib/components/SimpleSelect.tsx +2 -2
- package/apps/lib/components/SlideDatePicker.tsx +15 -4
- package/apps/lib/components/Stepper.tsx +329 -180
- package/apps/lib/components/Switch.tsx +2 -2
- package/apps/lib/components/TabSwitch.tsx +18 -12
- package/apps/lib/components/Table.tsx +1 -1
- package/apps/lib/components/Textarea.tsx +29 -4
- package/apps/lib/components/TreeDropDown.tsx +18 -6
- package/apps/lib/layouts/FieldSection.tsx +28 -2
- package/apps/lib/registry.json +7 -17
- package/apps/lib/tsconfig.tsbuildinfo +1 -1
- package/docs/components/action-button.md +3 -1
- package/docs/components/badge-field.md +4 -4
- package/docs/components/context-menu.md +3 -1
- package/docs/components/data-views/examples/filters.md +0 -1
- package/docs/components/data-views/index.md +1 -17
- package/docs/components/dropdown-menu.md +3 -0
- package/docs/components/form-builder.md +27 -1
- package/docs/components/header-bar.md +3 -2
- package/docs/components/input-field.md +3 -3
- package/docs/components/select.md +1 -1
- package/docs/components/stepper.md +119 -24
- package/docs/migration/changelog.md +13 -0
- package/docs/reference/tailwind-plugins.md +42 -0
- package/docs/tutorials/getting-started.md +32 -11
- package/package.json +1 -1
- package/apps/lib/components/DataViews/filters/summary.tsx +0 -65
- package/apps/lib/components/FormStepper.tsx +0 -272
- package/docs/components/form-stepper.md +0 -250
|
@@ -3,8 +3,7 @@ import React from "react";
|
|
|
3
3
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
4
4
|
import { cn } from "../utils/cn";
|
|
5
5
|
import { cva, VariantProps } from "class-variance-authority";
|
|
6
|
-
import {
|
|
7
|
-
import { Tooltip } from "./Tooltip";
|
|
6
|
+
import { ActionButton } from "./ActionButton";
|
|
8
7
|
import { MenuItemStyles } from "./DropdownMenu";
|
|
9
8
|
import { Themes } from "../utils/types";
|
|
10
9
|
|
|
@@ -18,6 +17,7 @@ const SelectTrigger = React.forwardRef<
|
|
|
18
17
|
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
19
18
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> &
|
|
20
19
|
VariantProps<typeof PopoverTriggerStyles> & {
|
|
20
|
+
/** Marks the trigger invalid: any non-undefined value turns on the negative border. */
|
|
21
21
|
errors?: string;
|
|
22
22
|
icon?: string;
|
|
23
23
|
theme?: Themes;
|
|
@@ -38,51 +38,50 @@ const SelectTrigger = React.forwardRef<
|
|
|
38
38
|
ref,
|
|
39
39
|
) => {
|
|
40
40
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
41
|
+
<SelectPrimitive.Trigger
|
|
42
|
+
data-theme={theme}
|
|
43
|
+
ref={ref}
|
|
44
|
+
className={cn(
|
|
45
|
+
PopoverTriggerStyles({
|
|
46
|
+
size,
|
|
47
|
+
variant,
|
|
48
|
+
error: errors !== undefined,
|
|
49
|
+
onTable,
|
|
50
|
+
}),
|
|
51
|
+
className,
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
<p
|
|
56
|
+
className={cn({
|
|
57
|
+
"[&_span]:text-[#A0A0A0]": !props.value,
|
|
58
|
+
})}
|
|
55
59
|
>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"[&_span]:text-[#A0A0A0]": !props.value,
|
|
59
|
-
})}
|
|
60
|
-
>
|
|
61
|
-
{children}
|
|
62
|
-
</p>
|
|
60
|
+
{children}
|
|
61
|
+
</p>
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
</
|
|
85
|
-
</
|
|
63
|
+
{/* The shared in-field action button. Its box tracks the trigger height the same way
|
|
64
|
+
InputField's does — a 30px field takes the 22px button, a 40px field the 32px one. */}
|
|
65
|
+
<ActionButton
|
|
66
|
+
as={"span"}
|
|
67
|
+
size={size === "XL" ? "M" : size === "S" ? "XS" : "S"}
|
|
68
|
+
className={cn([
|
|
69
|
+
"group-aria-expanded:bg-background-presentation-action-hover",
|
|
70
|
+
"group-aria-expanded:text-white",
|
|
71
|
+
])}
|
|
72
|
+
>
|
|
73
|
+
<i
|
|
74
|
+
className={cn(
|
|
75
|
+
"ri-arrow-down-s-line transition-all duration-100 ease-in-out group-aria-expanded:rotate-180",
|
|
76
|
+
{ "!text-[12px]": size === "S" },
|
|
77
|
+
{ "!text-[16px]": size === "M" },
|
|
78
|
+
{ "!text-[18px]": size === "L" },
|
|
79
|
+
{ "!text-[26px]": size === "XL" },
|
|
80
|
+
{ icon: icon },
|
|
81
|
+
)}
|
|
82
|
+
/>
|
|
83
|
+
</ActionButton>
|
|
84
|
+
</SelectPrimitive.Trigger>
|
|
86
85
|
);
|
|
87
86
|
},
|
|
88
87
|
);
|
|
@@ -139,10 +138,19 @@ const SelectContent = React.forwardRef<
|
|
|
139
138
|
ref={ref}
|
|
140
139
|
className={cn(SelectContentStyles({ variant }), className)}
|
|
141
140
|
position={position}
|
|
141
|
+
// Never taller than 368px, and never taller than the space Radix has on screen. Valid because
|
|
142
|
+
// `position` defaults to "popper", which is what publishes the variable.
|
|
143
|
+
style={{
|
|
144
|
+
maxHeight: "min(368px, var(--radix-select-content-available-height, 100vh))",
|
|
145
|
+
...props.style,
|
|
146
|
+
}}
|
|
142
147
|
{...props}
|
|
143
148
|
>
|
|
144
|
-
{/* Dedicated scroll viewport + boxed group, matching SearchableSelect's menu surface.
|
|
145
|
-
|
|
149
|
+
{/* Dedicated scroll viewport + boxed group, matching SearchableSelect's menu surface.
|
|
150
|
+
`flex-1 min-h-0` is what makes it scroll: without `min-h-0` a flex item refuses to shrink
|
|
151
|
+
below its content, so the list grew past the panel and `overflow-hidden` simply clipped
|
|
152
|
+
the rows off with no scrollbar. */}
|
|
153
|
+
<SelectPrimitive.Viewport className="flex-1 min-h-0 overflow-y-auto overflow-x-hidden rounded-[10px] scrollbar-hide">
|
|
146
154
|
<div className="flex flex-col gap-[1px] overflow-hidden rounded-[10px]">{children}</div>
|
|
147
155
|
</SelectPrimitive.Viewport>
|
|
148
156
|
</SelectPrimitive.Content>
|
|
@@ -176,7 +184,7 @@ const SelectItem = React.forwardRef<
|
|
|
176
184
|
>
|
|
177
185
|
<div>
|
|
178
186
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
179
|
-
<SelectPrimitive.ItemIndicator className="
|
|
187
|
+
<SelectPrimitive.ItemIndicator className="ms-auto flex shrink-0">
|
|
180
188
|
<i className="ri-check-line text-[16px]" />
|
|
181
189
|
</SelectPrimitive.ItemIndicator>
|
|
182
190
|
</div>
|
|
@@ -230,7 +238,8 @@ const SelectContentStyles = cva(
|
|
|
230
238
|
"data-[state=open]:animate-in",
|
|
231
239
|
"data-[state=open]:fade-in-0",
|
|
232
240
|
"z-[1000]",
|
|
233
|
-
|
|
241
|
+
// Panel height is set inline below from `min(368px, available-height)`; the class is kept off
|
|
242
|
+
// deliberately so the inline value governs.
|
|
234
243
|
],
|
|
235
244
|
{
|
|
236
245
|
variants: {
|
|
@@ -253,7 +262,11 @@ const SelectContentStyles = cva(
|
|
|
253
262
|
|
|
254
263
|
const PopoverTriggerStyles = cva(
|
|
255
264
|
[
|
|
256
|
-
|
|
265
|
+
// No radius here — every `size` variant sets its own. `twMerge` does NOT dedupe the
|
|
266
|
+
// `rounded-radius-*` classes (they are custom scale keys, not values it recognises), so a
|
|
267
|
+
// radius on the base would survive alongside the variant's and let CSS source order pick the
|
|
268
|
+
// winner: `md` is generated before `lg`, so a base `lg` would silently beat size S's `md`.
|
|
269
|
+
"flex flex-row justify-between items-center outline-none",
|
|
257
270
|
"[&_span]:text-content-presentation-action-light-primary",
|
|
258
271
|
"typography-body-small-regular",
|
|
259
272
|
"[&_p]:px-[10px] [&_p]:whitespace-nowrap",
|
|
@@ -299,12 +312,31 @@ const PopoverTriggerStyles = cva(
|
|
|
299
312
|
onTable: {
|
|
300
313
|
true: ["border-transparent", "bg-transparent"],
|
|
301
314
|
},
|
|
315
|
+
// No `[&_span]:h-/w-` here: the chevron is an `ActionButton` and sizes itself from its own
|
|
316
|
+
// `size` prop. Those descendant rules used to force its box, and being descendant selectors
|
|
317
|
+
// they outranked the button's own classes — they also hit the SelectValue text span, which
|
|
318
|
+
// only escaped being squashed because an inline element ignores width/height.
|
|
302
319
|
size: {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
320
|
+
// 24px tall — below the field scale's smallest step (30px), so it keeps its own
|
|
321
|
+
// `radius/md` rather than being rounded up to the 8px a real field would use.
|
|
322
|
+
// Heights are explicit because the trigger used to be sized by whichever chevron box the
|
|
323
|
+
// `[&_span]` rules imposed; now that the chevron sizes itself, the field must state its own.
|
|
324
|
+
//
|
|
325
|
+
// Every size states its padding so that `2×border + 2×padding + chevron` is exactly the
|
|
326
|
+
// trigger height — the chevron then sits an equal distance from all four edges instead of
|
|
327
|
+
// being flush to the border horizontally and centred vertically. Only XL had any padding
|
|
328
|
+
// before, which is why it was the only size that looked right.
|
|
329
|
+
//
|
|
330
|
+
// L and XL are the real field heights (30/40) and land on Figma's 4px. S and M have no
|
|
331
|
+
// Figma counterpart, so they take 3px — the most that still fits their chevron exactly.
|
|
332
|
+
S: ["h-[24px] p-[2px] rounded-radius-md [&_p]:typography-body-small-medium"],
|
|
333
|
+
// 28px and 30px — the field scale's S step (30px) is `radius/lg`.
|
|
334
|
+
M: ["h-[28px] p-[2px] rounded-radius-lg [&_p]:typography-body-medium-medium"],
|
|
335
|
+
L: ["h-[30px] p-[3px] rounded-radius-lg [&_p]:typography-body-large-medium"],
|
|
336
|
+
// 40px tall, so it is exactly InputField M and takes that size's `radius/xl` (12px).
|
|
337
|
+
// It sat at 8px before — the one place a 40px field in the system rounded like a 30px one.
|
|
306
338
|
XL: [
|
|
307
|
-
"h-[40px] p-[
|
|
339
|
+
"h-[40px] p-[3px] rounded-radius-xl [&_p]:typography-body-large-regular [&_p]:px-[4px]",
|
|
308
340
|
],
|
|
309
341
|
},
|
|
310
342
|
},
|
|
@@ -13,7 +13,7 @@ const SimpleSelectDropDown = ({ className, children, onClick }: SimpleSelectDrop
|
|
|
13
13
|
return (
|
|
14
14
|
<div
|
|
15
15
|
className={cn(
|
|
16
|
-
"absolute min-w-[100px] z-[20] top-[27px]
|
|
16
|
+
"absolute min-w-[100px] z-[20] top-[27px] start-0",
|
|
17
17
|
dropdownMenuStyles({ variant: "SystemStyle" }),
|
|
18
18
|
className,
|
|
19
19
|
)}
|
|
@@ -97,7 +97,7 @@ const SimpleSelectValue = ({
|
|
|
97
97
|
"w-fit",
|
|
98
98
|
"rounded-[6px]",
|
|
99
99
|
"outline-none",
|
|
100
|
-
"
|
|
100
|
+
"ps-[8px]",
|
|
101
101
|
className,
|
|
102
102
|
])}
|
|
103
103
|
>
|
|
@@ -47,7 +47,11 @@ export const SlideDatePicker = forwardRef<HTMLInputElement, SlideDatePickerProps
|
|
|
47
47
|
const defaultPickerValue = {
|
|
48
48
|
year: String(today.getFullYear()),
|
|
49
49
|
month: String(today.getMonth() + 1),
|
|
50
|
-
|
|
50
|
+
// Zero-padded to match `getDayArray`, which emits "01".."31". Unpadded, a single-digit day
|
|
51
|
+
// ("5") matches no item in the wheel, so the picker cannot select the current date and falls
|
|
52
|
+
// back to the first day of the month — the field then shows the wrong date. Only reproducible
|
|
53
|
+
// on the 1st–9th, which is why it survived this long.
|
|
54
|
+
day: String(today.getDate()).padStart(2, "0"),
|
|
51
55
|
hour: String(today.getHours()),
|
|
52
56
|
minute: String(today.getMinutes()),
|
|
53
57
|
time: today.getHours() < 12 ? "AM" : "PM",
|
|
@@ -60,7 +64,9 @@ export const SlideDatePicker = forwardRef<HTMLInputElement, SlideDatePickerProps
|
|
|
60
64
|
|
|
61
65
|
const currentYear = new Date().getFullYear();
|
|
62
66
|
const years = Array.from({ length: 200 }, (_, i) => `${currentYear - 100 + i}`);
|
|
63
|
-
|
|
67
|
+
// No padding: these must match `defaultPickerValue.month`, which is unpadded. (This previously
|
|
68
|
+
// read `padStart(2, "")` — an empty pad string, so it never padded anything.)
|
|
69
|
+
const months = Array.from({ length: 12 }, (_, i) => String(i + 1));
|
|
64
70
|
const days = getDayArray(Number(pickerValue.year), Number(pickerValue.month));
|
|
65
71
|
const monthsNames = [
|
|
66
72
|
"January",
|
|
@@ -143,9 +149,14 @@ export const SlideDatePicker = forwardRef<HTMLInputElement, SlideDatePickerProps
|
|
|
143
149
|
|
|
144
150
|
return (
|
|
145
151
|
<Popover onOpenChange={setIsOpen}>
|
|
146
|
-
|
|
152
|
+
{/* `theme` is deliberately NOT passed to the field: only the picker panel below is pinned
|
|
153
|
+
dark. The field follows the surrounding page instead, so it matches the other inputs
|
|
154
|
+
next to it. Note it must not be handed down as `data-theme` either — `asChild` merges
|
|
155
|
+
trigger props onto the child, which would land the attribute on the bare <input> and
|
|
156
|
+
leave its text resolving dark tokens inside a light field (white on white). */}
|
|
157
|
+
<PopoverTrigger ref={triggerRef} asChild className="w-full flex-1">
|
|
147
158
|
{isValidElement(children) ? (
|
|
148
|
-
cloneElement(children as React.ReactElement<HTMLInputElement>, {
|
|
159
|
+
cloneElement(children as React.ReactElement<HTMLInputElement & { theme?: string }>, {
|
|
149
160
|
value:
|
|
150
161
|
(children as React.ReactElement<HTMLInputElement>).props.value ?? formattedValue,
|
|
151
162
|
type: "input",
|