torch-glare 2.1.1 → 2.1.3

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 (73) hide show
  1. package/apps/lib/components/Avatar.tsx +1 -1
  2. package/apps/lib/components/BadgeField.tsx +2 -2
  3. package/apps/lib/components/Card.tsx +68 -54
  4. package/apps/lib/components/DataViews/ARCHITECTURE.md +439 -0
  5. package/apps/lib/components/DataViews/DataViewRadio.tsx +47 -0
  6. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +427 -0
  7. package/apps/lib/components/DataViews/DataViewsHeader.tsx +228 -0
  8. package/apps/lib/components/DataViews/DataViewsLayout.tsx +330 -0
  9. package/apps/lib/components/DataViews/FilterPanel.tsx +469 -0
  10. package/apps/lib/components/DataViews/HeaderSearch.tsx +97 -0
  11. package/apps/lib/components/DataViews/InboxView.tsx +495 -0
  12. package/apps/lib/components/DataViews/InboxViewCard.tsx +136 -0
  13. package/apps/lib/components/DataViews/KanbanView.tsx +353 -0
  14. package/apps/lib/components/DataViews/PanelControls.tsx +49 -0
  15. package/apps/lib/components/DataViews/SettingsPanel.tsx +285 -0
  16. package/apps/lib/components/DataViews/TableView.tsx +232 -0
  17. package/apps/lib/components/DataViews/TreeView.tsx +392 -0
  18. package/apps/lib/components/DataViews/badgeAdapter.ts +45 -0
  19. package/apps/lib/components/DataViews/fieldRenderers.tsx +334 -0
  20. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +113 -0
  21. package/apps/lib/components/DataViews/filters/PresetChips.tsx +45 -0
  22. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +154 -0
  23. package/apps/lib/components/DataViews/index.ts +36 -0
  24. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +54 -0
  25. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +77 -0
  26. package/apps/lib/components/DataViews/types.ts +206 -0
  27. package/apps/lib/components/Radio.tsx +18 -21
  28. package/apps/lib/components/Switch.tsx +3 -1
  29. package/apps/lib/components/Table.tsx +1 -1
  30. package/apps/lib/components/TreeFolder/TreeFolder.tsx +410 -0
  31. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +80 -0
  32. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +363 -0
  33. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +60 -0
  34. package/apps/lib/components/TreeFolder/icons.tsx +63 -0
  35. package/apps/lib/components/TreeFolder/index.ts +17 -0
  36. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +114 -0
  37. package/apps/lib/components/TreeFolder/types.ts +77 -0
  38. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +261 -0
  39. package/apps/lib/hooks/useDataViewsState.ts +169 -0
  40. package/apps/lib/hooks/useIsMobile.ts +21 -0
  41. package/apps/lib/layouts/DataViewCard.tsx +76 -0
  42. package/apps/lib/utils/dataViews/columnUtils.ts +130 -0
  43. package/apps/lib/utils/dataViews/fieldUtils.ts +198 -0
  44. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +364 -0
  45. package/apps/lib/utils/dataViews/pathUtils.ts +132 -0
  46. package/apps/lib/utils/dataViews/rangeUtils.ts +225 -0
  47. package/apps/lib/utils/dataViews/treeUtils.ts +403 -0
  48. package/dist/bin/index.js +3 -3
  49. package/dist/bin/index.js.map +1 -1
  50. package/dist/src/commands/add.d.ts.map +1 -1
  51. package/dist/src/commands/add.js +29 -6
  52. package/dist/src/commands/add.js.map +1 -1
  53. package/dist/src/commands/utils.d.ts.map +1 -1
  54. package/dist/src/commands/utils.js +22 -2
  55. package/dist/src/commands/utils.js.map +1 -1
  56. package/dist/src/shared/copyComponentsRecursively.d.ts.map +1 -1
  57. package/dist/src/shared/copyComponentsRecursively.js +17 -2
  58. package/dist/src/shared/copyComponentsRecursively.js.map +1 -1
  59. package/dist/src/shared/getDependenciesAndInstallNestedComponents.d.ts +18 -4
  60. package/dist/src/shared/getDependenciesAndInstallNestedComponents.d.ts.map +1 -1
  61. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js +110 -40
  62. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js.map +1 -1
  63. package/docs/components/data-views-config-panel.md +204 -0
  64. package/docs/components/data-views-layout.md +270 -0
  65. package/docs/components/form-stepper.md +244 -0
  66. package/docs/components/stepper.md +215 -0
  67. package/docs/components/timeline.md +248 -0
  68. package/package.json +6 -6
  69. package/apps/lib/components/Charts-dev.tsx +0 -365
  70. package/apps/lib/components/Command-dev.tsx +0 -151
  71. package/apps/lib/components/IosDatePicker-dev.tsx +0 -341
  72. /package/docs/components/{labeled-checkbox.md → labeled-check-box.md} +0 -0
  73. /package/docs/components/{tree-dropdown.md → tree-drop-down.md} +0 -0
@@ -0,0 +1,54 @@
1
+ "use client"
2
+
3
+ import { Drawer } from "vaul"
4
+ import { Menu, X } from "lucide-react"
5
+ import type { ReactNode } from "react"
6
+
7
+ type Props = {
8
+ open: boolean
9
+ onOpenChange: (open: boolean) => void
10
+ children: ReactNode
11
+ }
12
+
13
+ export function TreeDrawer({ open, onOpenChange, children }: Props) {
14
+ return (
15
+ <Drawer.Root open={open} onOpenChange={onOpenChange} direction="left">
16
+ <Drawer.Portal>
17
+ <Drawer.Overlay className="fixed inset-0 bg-black/40 z-40" />
18
+ <Drawer.Content
19
+ className="fixed inset-y-0 left-0 z-50 w-72 bg-background-presentation-body-overlay-primary border-r border-border-presentation-global-primary outline-none flex flex-col"
20
+ >
21
+ <div className="flex items-center justify-between p-3 border-b border-border-presentation-global-primary">
22
+ <Drawer.Title className="text-sm font-semibold text-content-presentation-global-primary">
23
+ Tree
24
+ </Drawer.Title>
25
+ <button
26
+ type="button"
27
+ onClick={() => onOpenChange(false)}
28
+ aria-label="Close tree"
29
+ className="p-1 rounded text-content-presentation-global-tertiary hover:text-content-presentation-global-primary"
30
+ >
31
+ <X className="w-4 h-4" />
32
+ </button>
33
+ </div>
34
+ <div className="flex-1 overflow-y-auto p-2">
35
+ {children}
36
+ </div>
37
+ </Drawer.Content>
38
+ </Drawer.Portal>
39
+ </Drawer.Root>
40
+ )
41
+ }
42
+
43
+ export function TreeDrawerTrigger({ onClick }: { onClick: () => void }) {
44
+ return (
45
+ <button
46
+ type="button"
47
+ onClick={onClick}
48
+ aria-label="Open tree"
49
+ className="inline-flex items-center justify-center h-8 w-8 rounded-md border border-border-presentation-global-primary text-content-presentation-global-secondary hover:text-content-presentation-global-primary"
50
+ >
51
+ <Menu className="w-4 h-4" />
52
+ </button>
53
+ )
54
+ }
@@ -0,0 +1,77 @@
1
+ "use client"
2
+
3
+ import { useMemo } from "react"
4
+ import type { FieldConfig } from "../types"
5
+ import type { TreeNode } from "../../../utils/dataViews/treeUtils"
6
+ import { getByPath } from "../../../utils/dataViews/pathUtils"
7
+ import { TreeFolder } from "../../TreeFolder"
8
+ import type {
9
+ TreeFolderMoveArgs,
10
+ TreeFolderNode,
11
+ } from "../../TreeFolder"
12
+
13
+ type Props = {
14
+ roots: TreeNode[]
15
+ expanded: Set<string>
16
+ selectedId: string | null
17
+ labelField: FieldConfig
18
+ dndEnabled: boolean
19
+ onToggle: (id: string) => void
20
+ onSelect: (id: string) => void
21
+ onMove?: (args: TreeFolderMoveArgs) => void
22
+ }
23
+
24
+ function toFolderNode(node: TreeNode, labelField: FieldConfig): TreeFolderNode {
25
+ const labelValue = getByPath(node.record, labelField.path)
26
+ const name = labelValue == null ? node.id : String(labelValue)
27
+ const children = node.children.length
28
+ ? node.children.map((c) => toFolderNode(c, labelField))
29
+ : undefined
30
+ return {
31
+ id: node.id,
32
+ name,
33
+ type: children ? "folder" : "file",
34
+ data: node.record,
35
+ children,
36
+ }
37
+ }
38
+
39
+ export function TreeSidebar({
40
+ roots,
41
+ expanded,
42
+ selectedId,
43
+ labelField,
44
+ dndEnabled,
45
+ onToggle,
46
+ onSelect,
47
+ onMove,
48
+ }: Props) {
49
+ const folderData = useMemo(
50
+ () => roots.map((r) => toFolderNode(r, labelField)),
51
+ [roots, labelField],
52
+ )
53
+
54
+ const expandedIds = useMemo(() => Array.from(expanded), [expanded])
55
+
56
+ return (
57
+ <TreeFolder
58
+ data={folderData}
59
+ selectedId={selectedId}
60
+ onSelectionChange={(id) => {
61
+ if (id) onSelect(id)
62
+ }}
63
+ expandedIds={expandedIds}
64
+ onExpandedChange={(next) => {
65
+ const before = new Set(expandedIds)
66
+ const after = new Set(next)
67
+ for (const id of after) if (!before.has(id)) onToggle(id)
68
+ for (const id of before) if (!after.has(id)) onToggle(id)
69
+ }}
70
+ dndEnabled={dndEnabled}
71
+ onMove={onMove}
72
+ showHeader={false}
73
+ showBreadcrumb={true}
74
+ highlightAncestors={true}
75
+ />
76
+ )
77
+ }
@@ -0,0 +1,206 @@
1
+ import type React from "react"
2
+
3
+ export type ViewType = "table" | "kanban" | "inbox" | "tree"
4
+
5
+ export type TreeConfig = {
6
+ childrenField?: string
7
+ parentField?: string
8
+ idField?: string
9
+ orderField?: string
10
+ nodeLabel?: string
11
+ defaultExpanded?: "all" | "roots" | "none"
12
+ /** Right-pane mode for the selected tree node. `"details"` is accepted as a
13
+ * deprecated alias of `"card"` for backward compatibility. */
14
+ defaultRightPane?: "table" | "card" | "details"
15
+ dndEnabled?: boolean
16
+ }
17
+
18
+ export type ViewVisibility = {
19
+ table?: boolean
20
+ kanban?: boolean
21
+ inbox?: boolean
22
+ tree?: boolean
23
+ }
24
+
25
+ export type DynamicRecord = Record<string, any>
26
+
27
+ export type DynamicColumnConfig = {
28
+ id: string
29
+ label: string
30
+ visible: boolean
31
+ order: number
32
+ type?: "text" | "number" | "date" | "badge" | "array" | "boolean"
33
+ render?: (value: any, row: DynamicRecord) => React.ReactNode
34
+ }
35
+
36
+ export type DynamicFilterConfig = {
37
+ id: string
38
+ label?: string
39
+ enabled?: boolean
40
+ order?: number
41
+ options?: string[] | { label: string; value: string }[]
42
+ render?: (value: string, isSelected: boolean) => React.ReactNode
43
+ onChange?: (selectedValues: string[]) => void
44
+ }
45
+
46
+ export type NumericRangeFilter = { kind: "number"; min?: number; max?: number }
47
+ export type DateRangeFilter = { kind: "date"; from?: string; to?: string }
48
+ export type RangeFilter = NumericRangeFilter | DateRangeFilter
49
+ export type FilterValue = string[] | RangeFilter
50
+ export type FilterState = Record<string, FilterValue>
51
+
52
+ export type FieldPreset =
53
+ | { label: string; min?: number; max?: number }
54
+ | { label: string; from?: string; to?: string }
55
+
56
+ // Palette keys for the Kanban column header pill. Kept in lockstep with
57
+ // `COLUMN_PALETTE` in KanbanView.tsx so consumers can pick a color per status
58
+ // via `FieldConfig.kanbanVariants`.
59
+ export type KanbanColumnColor =
60
+ | "gray"
61
+ | "purple"
62
+ | "orange"
63
+ | "blue"
64
+ | "green"
65
+ | "red"
66
+
67
+ export type BadgeVariant =
68
+ | "green"
69
+ | "greenLight"
70
+ | "cocktailGreen"
71
+ | "yellow"
72
+ | "redOrange"
73
+ | "redLight"
74
+ | "rose"
75
+ | "purple"
76
+ | "bluePurple"
77
+ | "blue"
78
+ | "navy"
79
+ | "gray"
80
+ | "highlight"
81
+
82
+ export type FieldType =
83
+ | "text"
84
+ | "number"
85
+ | "date"
86
+ | "boolean"
87
+ | "hidden"
88
+ | "enum-badge"
89
+ | "badge-array"
90
+ | "currency"
91
+ | "number-format"
92
+ | "progress-bar"
93
+ | "star-rating"
94
+ | "icon-text"
95
+ | "two-line"
96
+ | "avatar"
97
+ | "link"
98
+ | "image"
99
+ | "date-format"
100
+
101
+ export type CurrencyOptions = {
102
+ symbol?: string
103
+ locale?: string
104
+ decimals?: number
105
+ code?: string
106
+ }
107
+
108
+ export type FieldConfig = {
109
+ path: string
110
+ label?: string
111
+ type?: FieldType
112
+ visible?: boolean
113
+ order?: number
114
+
115
+ variants?: Record<string, BadgeVariant>
116
+ defaultVariant?: BadgeVariant
117
+
118
+ // Per-status overrides for the Kanban board view. Keys must match
119
+ // `variants` keys (or any value present in the data). Lets consumers set a
120
+ // human-friendly column title and pick a column pill color without affecting
121
+ // the badge color used elsewhere.
122
+ kanbanVariants?: Record<
123
+ string,
124
+ { label?: string; color?: KanbanColumnColor }
125
+ >
126
+
127
+
128
+ variant?: BadgeVariant
129
+ limit?: number
130
+
131
+ currency?: string | CurrencyOptions
132
+ format?: Intl.NumberFormatOptions
133
+
134
+ thresholds?: [number, number]
135
+
136
+ max?: number
137
+
138
+ icon?: string
139
+ iconPosition?: "before" | "after"
140
+
141
+ secondaryPath?: string
142
+
143
+ linkType?: "mailto" | "tel" | "url"
144
+
145
+ fallbackPath?: string
146
+
147
+ dateFormat?: string | Intl.DateTimeFormatOptions
148
+
149
+ trueLabel?: string
150
+ falseLabel?: string
151
+ trueVariant?: BadgeVariant
152
+ falseVariant?: BadgeVariant
153
+
154
+ filterable?: boolean
155
+ filterLabel?: string
156
+ filterOptions?: string[] | { label: string; value: string }[]
157
+ /**
158
+ * Categorical filter selection mode.
159
+ * - "multi" (default): checkboxes, multi-select. FilterValue is the array of picked options.
160
+ * - "single": radios, single-select. FilterValue is a 1-element array.
161
+ */
162
+ filterMode?: "single" | "multi"
163
+ presets?: FieldPreset[]
164
+ rangeMin?: number
165
+ rangeMax?: number
166
+ rangeStep?: number
167
+ onFilterChange?: (value: FilterValue) => void
168
+
169
+ render?: (value: any, row: DynamicRecord) => React.ReactNode
170
+ }
171
+
172
+ export type InboxConfig = {
173
+ starredField?: string | null
174
+ readField?: string | null
175
+ attachmentField?: string | null
176
+ priorityField?: string | null
177
+ titlePath?: string
178
+ previewPath?: string
179
+ }
180
+
181
+ export type ColumnConfig = {
182
+ id: string
183
+ label: string
184
+ visible: boolean
185
+ order: number
186
+ }
187
+
188
+ export type ViewConfig = {
189
+ defaultView: ViewType
190
+ tableColumns: ColumnConfig[]
191
+ kanbanGroupBy: string
192
+ showFilters: boolean
193
+ showPreviewPane: boolean
194
+ sortBy: string
195
+ sortOrder: "asc" | "desc"
196
+ }
197
+
198
+ export const defaultConfig: ViewConfig = {
199
+ defaultView: "table",
200
+ tableColumns: [],
201
+ kanbanGroupBy: "",
202
+ showFilters: true,
203
+ showPreviewPane: true,
204
+ sortBy: "",
205
+ sortOrder: "desc",
206
+ }
@@ -1,9 +1,8 @@
1
- 'use client'
1
+ "use client";
2
2
  import { cn } from "../utils/cn";
3
3
  import { cva } from "class-variance-authority";
4
- import * as React from "react"
5
- import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
6
-
4
+ import * as React from "react";
5
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
7
6
 
8
7
  const RadioGroup = React.forwardRef<
9
8
  React.ElementRef<typeof RadioGroupPrimitive.Root>,
@@ -11,37 +10,35 @@ const RadioGroup = React.forwardRef<
11
10
  >(({ className, ...props }, ref) => {
12
11
  return (
13
12
  <RadioGroupPrimitive.Root
14
- className={cn("grid gap-2", className)}
13
+ className={cn("grid gap-0.5", className)}
15
14
  {...props}
16
15
  ref={ref}
17
16
  />
18
- )
19
- })
20
- RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
17
+ );
18
+ });
19
+ RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
21
20
 
22
21
  const Radio = React.forwardRef<
23
22
  React.ElementRef<typeof RadioGroupPrimitive.Item>,
24
- React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> & { size?: "S" | "M" }
23
+ React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> & {
24
+ size?: "S" | "M";
25
+ }
25
26
  >(({ className, size = "S", ...props }, ref) => {
26
27
  return (
27
28
  <RadioGroupPrimitive.Item
28
29
  ref={ref}
29
- className={cn(
30
- glareRadioStyles({ size }),
31
- className
32
- )}
30
+ className={cn(glareRadioStyles({ size }), className)}
33
31
  {...props}
34
32
  >
35
33
  <RadioGroupPrimitive.Indicator className="bg-white rounded-full flex items-center justify-center shrink-0">
36
34
  <i className="ri-record-circle-fill text-background-presentation-state-information-primary leading-none shrink-0"></i>
37
35
  </RadioGroupPrimitive.Indicator>
38
36
  </RadioGroupPrimitive.Item>
39
- )
40
- })
41
- Radio.displayName = "Radio"
42
-
43
- export { RadioGroup, Radio }
37
+ );
38
+ });
39
+ Radio.displayName = "Radio";
44
40
 
41
+ export { RadioGroup, Radio };
45
42
 
46
43
  const glareRadioStyles = cva(
47
44
  [
@@ -61,6 +58,6 @@ const glareRadioStyles = cva(
61
58
  S: ["w-[12px]", "h-[12px] [&_i]:text-[10px] [&_i]:scale-[1.5]"],
62
59
  M: ["w-[24px]", "h-[24px] [&_i]:text-[20px] [&_i]:scale-[1.47]"],
63
60
  },
64
- }
65
- }
66
- );
61
+ },
62
+ },
63
+ );
@@ -17,7 +17,9 @@ const Switch = React.forwardRef<
17
17
  >
18
18
  <SwitchPrimitives.Thumb
19
19
  className={cn(
20
- "pointer-events-none block w-[24px] h-[24px] rounded-full bg-background-presentation-switcher-knob shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-[21px] data-[state=unchecked]:translate-x-0"
20
+ "pointer-events-none block w-[24px] h-[24px] rounded-full bg-background-presentation-switcher-knob shadow-lg ring-0 transition-transform",
21
+ "data-[state=checked]:translate-x-[21px] data-[state=unchecked]:translate-x-0",
22
+ "rtl:data-[state=checked]:-translate-x-[21px] rtl:data-[state=unchecked]:translate-x-0"
21
23
  )}
22
24
  />
23
25
  </SwitchPrimitives.Root>
@@ -128,7 +128,7 @@ const TableHead = React.forwardRef<
128
128
  <th
129
129
  ref={headRef}
130
130
  className={cn(
131
- "relative py-[2px] px-[2px] border-b-[2px] border-border-presentation-table-header",
131
+ "relative py-[6px] px-[4px] border-b-[2px] border-border-presentation-table-header",
132
132
  )}
133
133
  >
134
134
  <div