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.
Files changed (56) hide show
  1. package/apps/lib/components/ActionButton.tsx +39 -6
  2. package/apps/lib/components/Badge.tsx +5 -2
  3. package/apps/lib/components/BadgeField.tsx +71 -67
  4. package/apps/lib/components/Button.tsx +4 -4
  5. package/apps/lib/components/Calendar.tsx +7 -17
  6. package/apps/lib/components/Card.tsx +2 -1
  7. package/apps/lib/components/ColorPicker.tsx +1 -1
  8. package/apps/lib/components/ContextMenu.tsx +65 -22
  9. package/apps/lib/components/DataViews/context.ts +2 -2
  10. package/apps/lib/components/DataViews/data-views.tsx +3 -3
  11. package/apps/lib/components/DataViews/filters/filters.tsx +0 -2
  12. package/apps/lib/components/DataViews/views/table-view.tsx +190 -153
  13. package/apps/lib/components/Drawer.tsx +18 -1
  14. package/apps/lib/components/DropdownMenu.tsx +65 -22
  15. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +19 -5
  16. package/apps/lib/components/FormBuilder/types.ts +16 -0
  17. package/apps/lib/components/FormRenderer/form-renderer.tsx +16 -5
  18. package/apps/lib/components/FormRenderer/stepper.tsx +22 -16
  19. package/apps/lib/components/HeaderBar.tsx +51 -53
  20. package/apps/lib/components/Input.tsx +19 -4
  21. package/apps/lib/components/InputField.tsx +46 -47
  22. package/apps/lib/components/Popover.tsx +108 -56
  23. package/apps/lib/components/SearchableSelect.tsx +22 -17
  24. package/apps/lib/components/SearchableTree.tsx +33 -17
  25. package/apps/lib/components/SearchableTreeDialog.tsx +21 -12
  26. package/apps/lib/components/SectionBlock.tsx +3 -1
  27. package/apps/lib/components/Select.tsx +86 -54
  28. package/apps/lib/components/SimpleSelect.tsx +2 -2
  29. package/apps/lib/components/SlideDatePicker.tsx +15 -4
  30. package/apps/lib/components/Stepper.tsx +329 -180
  31. package/apps/lib/components/Switch.tsx +2 -2
  32. package/apps/lib/components/TabSwitch.tsx +18 -12
  33. package/apps/lib/components/Table.tsx +1 -1
  34. package/apps/lib/components/Textarea.tsx +29 -4
  35. package/apps/lib/components/TreeDropDown.tsx +18 -6
  36. package/apps/lib/layouts/FieldSection.tsx +28 -2
  37. package/apps/lib/registry.json +7 -17
  38. package/apps/lib/tsconfig.tsbuildinfo +1 -1
  39. package/docs/components/action-button.md +3 -1
  40. package/docs/components/badge-field.md +4 -4
  41. package/docs/components/context-menu.md +3 -1
  42. package/docs/components/data-views/examples/filters.md +0 -1
  43. package/docs/components/data-views/index.md +1 -17
  44. package/docs/components/dropdown-menu.md +3 -0
  45. package/docs/components/form-builder.md +27 -1
  46. package/docs/components/header-bar.md +3 -2
  47. package/docs/components/input-field.md +3 -3
  48. package/docs/components/select.md +1 -1
  49. package/docs/components/stepper.md +119 -24
  50. package/docs/migration/changelog.md +13 -0
  51. package/docs/reference/tailwind-plugins.md +42 -0
  52. package/docs/tutorials/getting-started.md +32 -11
  53. package/package.json +1 -1
  54. package/apps/lib/components/DataViews/filters/summary.tsx +0 -65
  55. package/apps/lib/components/FormStepper.tsx +0 -272
  56. 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 { Button } from "./Button";
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
- <Tooltip toolTipSide={"top"} open={errors !== undefined} text={errors}>
42
- <SelectPrimitive.Trigger
43
- data-theme={theme}
44
- ref={ref}
45
- className={cn(
46
- PopoverTriggerStyles({
47
- size,
48
- variant,
49
- error: errors !== undefined,
50
- onTable,
51
- }),
52
- className,
53
- )}
54
- {...props}
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
- <p
57
- className={cn({
58
- "[&_span]:text-[#A0A0A0]": !props.value,
59
- })}
60
- >
61
- {children}
62
- </p>
60
+ {children}
61
+ </p>
63
62
 
64
- <Button
65
- as={"span"}
66
- buttonType="icon"
67
- size={"L"}
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
- </Button>
84
- </SelectPrimitive.Trigger>
85
- </Tooltip>
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
- <SelectPrimitive.Viewport className="overflow-y-auto overflow-x-hidden rounded-[10px] scrollbar-hide">
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="ml-auto flex shrink-0">
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
- "max-h-[368px]",
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
- "flex flex-row rounded-[8px] justify-between items-center outline-none",
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
- S: ["rounded-[6px] [&_span]:h-[22px] [&_span]:w-[22px] [&_p]:typography-body-small-medium"],
304
- M: ["[&_span]:h-[26px] [&_span]:w-[26px] [&_p]:typography-body-medium-medium"],
305
- L: ["[&_span]:h-[28px] [&_span]:w-[28px] [&_p]:typography-body-large-medium"],
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-[4px] rounded-[8px] [&_span]:h-[32px] [&_span]:w-[32px] [&_p]:typography-body-large-regular [&_p]:px-[4px]",
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] left-0",
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
- "pl-[8px]",
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
- day: String(today.getDate()),
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
- const months = Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, ""));
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
- <PopoverTrigger ref={triggerRef} asChild data-theme={theme} className="w-full flex-1">
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",