@torch-ui/solid 0.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 (118) hide show
  1. package/README.md +166 -0
  2. package/package.json +67 -0
  3. package/src/components/actions/Button.tsx +612 -0
  4. package/src/components/actions/ButtonGroup.tsx +728 -0
  5. package/src/components/actions/Copy.tsx +98 -0
  6. package/src/components/actions/DarkModeToggle.tsx +80 -0
  7. package/src/components/actions/Link.tsx +37 -0
  8. package/src/components/actions/index.ts +19 -0
  9. package/src/components/actions/useCopyToClipboard.ts +90 -0
  10. package/src/components/charts/Chart.tsx +331 -0
  11. package/src/components/charts/Sparkline.tsx +156 -0
  12. package/src/components/charts/index.ts +13 -0
  13. package/src/components/data-display/Avatar.tsx +208 -0
  14. package/src/components/data-display/AvatarGroup.tsx +228 -0
  15. package/src/components/data-display/Badge.tsx +70 -0
  16. package/src/components/data-display/Carousel.tsx +214 -0
  17. package/src/components/data-display/ColorSwatch.tsx +56 -0
  18. package/src/components/data-display/DataTable.tsx +886 -0
  19. package/src/components/data-display/EmptyState.tsx +61 -0
  20. package/src/components/data-display/Image.tsx +277 -0
  21. package/src/components/data-display/Kbd.tsx +114 -0
  22. package/src/components/data-display/Persona.tsx +78 -0
  23. package/src/components/data-display/StatCard.tsx +338 -0
  24. package/src/components/data-display/Table.tsx +147 -0
  25. package/src/components/data-display/Tag.tsx +91 -0
  26. package/src/components/data-display/Timeline.tsx +200 -0
  27. package/src/components/data-display/TreeView.tsx +172 -0
  28. package/src/components/data-display/Video.tsx +95 -0
  29. package/src/components/data-display/avatar-utils.ts +32 -0
  30. package/src/components/data-display/index.ts +81 -0
  31. package/src/components/feedback/Loading.tsx +159 -0
  32. package/src/components/feedback/Progress.tsx +321 -0
  33. package/src/components/feedback/Skeleton.tsx +62 -0
  34. package/src/components/feedback/SkeletonBlocks.tsx +222 -0
  35. package/src/components/feedback/Toast.tsx +648 -0
  36. package/src/components/feedback/index.ts +44 -0
  37. package/src/components/feedback/password/PasswordStrengthIndicator.tsx +232 -0
  38. package/src/components/feedback/password/password-strength.ts +115 -0
  39. package/src/components/feedback/password/password-validation-data.ts +66 -0
  40. package/src/components/feedback/password/password-validation.ts +93 -0
  41. package/src/components/forms/Autocomplete.tsx +268 -0
  42. package/src/components/forms/Checkbox.tsx +155 -0
  43. package/src/components/forms/CodeInput.tsx +237 -0
  44. package/src/components/forms/ColorPicker/ColorPicker.tsx +469 -0
  45. package/src/components/forms/ColorPicker/color-utils.ts +75 -0
  46. package/src/components/forms/ColorPicker/index.ts +2 -0
  47. package/src/components/forms/DatePicker.tsx +516 -0
  48. package/src/components/forms/DateRangePicker.tsx +464 -0
  49. package/src/components/forms/FieldPicker.tsx +64 -0
  50. package/src/components/forms/FileUpload.tsx +614 -0
  51. package/src/components/forms/FilterBuilder/FilterGroupBlock.ts +6 -0
  52. package/src/components/forms/FilterBuilder.tsx +16 -0
  53. package/src/components/forms/FilterRuleRow.tsx +68 -0
  54. package/src/components/forms/Input.tsx +200 -0
  55. package/src/components/forms/MultiSelect.tsx +361 -0
  56. package/src/components/forms/NumberField.tsx +145 -0
  57. package/src/components/forms/RadioGroup.tsx +135 -0
  58. package/src/components/forms/RelativeDateDefaultInput.tsx +62 -0
  59. package/src/components/forms/ReorderableList.tsx +163 -0
  60. package/src/components/forms/Select.tsx +268 -0
  61. package/src/components/forms/Slider.tsx +260 -0
  62. package/src/components/forms/Switch.tsx +135 -0
  63. package/src/components/forms/TextArea.tsx +202 -0
  64. package/src/components/forms/ViewCustomizer.tsx +44 -0
  65. package/src/components/forms/index.ts +43 -0
  66. package/src/components/layout/Accordion.tsx +110 -0
  67. package/src/components/layout/Alert.tsx +156 -0
  68. package/src/components/layout/BlockQuote.tsx +70 -0
  69. package/src/components/layout/Card.tsx +166 -0
  70. package/src/components/layout/CodeBlock/CodeBlock.tsx +477 -0
  71. package/src/components/layout/CodeBlock/code-block-tokens.css +104 -0
  72. package/src/components/layout/CodeBlock/prism.ts +81 -0
  73. package/src/components/layout/Collapsible.tsx +84 -0
  74. package/src/components/layout/Container.tsx +55 -0
  75. package/src/components/layout/Divider.tsx +64 -0
  76. package/src/components/layout/Form.tsx +39 -0
  77. package/src/components/layout/FormActions.tsx +50 -0
  78. package/src/components/layout/Grid.tsx +53 -0
  79. package/src/components/layout/PageHeading.tsx +46 -0
  80. package/src/components/layout/PromptWithAction.tsx +49 -0
  81. package/src/components/layout/Section.tsx +60 -0
  82. package/src/components/layout/TablePanel.tsx +24 -0
  83. package/src/components/layout/TableView/TableView.tsx +1018 -0
  84. package/src/components/layout/TableView/index.ts +3 -0
  85. package/src/components/layout/TableView/types.ts +51 -0
  86. package/src/components/layout/WizardStep.tsx +40 -0
  87. package/src/components/layout/WizardStepper.tsx +173 -0
  88. package/src/components/layout/index.ts +96 -0
  89. package/src/components/navigation/Breadcrumbs.tsx +66 -0
  90. package/src/components/navigation/DropdownMenu.tsx +86 -0
  91. package/src/components/navigation/MegaMenu.tsx +480 -0
  92. package/src/components/navigation/NavigationMenu.tsx +305 -0
  93. package/src/components/navigation/Pagination.tsx +298 -0
  94. package/src/components/navigation/Sidebar.tsx +280 -0
  95. package/src/components/navigation/Tabs.tsx +122 -0
  96. package/src/components/navigation/ViewSwitcher.tsx +314 -0
  97. package/src/components/navigation/index.ts +66 -0
  98. package/src/components/overlays/AlertDialog.tsx +174 -0
  99. package/src/components/overlays/ContextMenu.tsx +65 -0
  100. package/src/components/overlays/Dialog.tsx +279 -0
  101. package/src/components/overlays/Drawer.tsx +370 -0
  102. package/src/components/overlays/HoverCard.tsx +107 -0
  103. package/src/components/overlays/Popover.tsx +73 -0
  104. package/src/components/overlays/Tooltip.tsx +31 -0
  105. package/src/components/overlays/index.ts +71 -0
  106. package/src/components/typography/Code.tsx +72 -0
  107. package/src/components/typography/Icon.tsx +36 -0
  108. package/src/components/typography/index.ts +10 -0
  109. package/src/env.d.ts +9 -0
  110. package/src/index.ts +13 -0
  111. package/src/styles/theme.css +226 -0
  112. package/src/types/avatar-types.ts +11 -0
  113. package/src/types/filter-types.ts +35 -0
  114. package/src/utilities/classNames.ts +6 -0
  115. package/src/utilities/componentSize.ts +46 -0
  116. package/src/utilities/i18n.tsx +60 -0
  117. package/src/utilities/mergeRefs.ts +12 -0
  118. package/src/utilities/relativeDateDefault.ts +14 -0
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Composable skeleton blocks for common layouts (Card, Table, Section, etc.).
3
+ * These do NOT set role="status" or aria-label — they are intended to be
4
+ * wrapped by a container that provides accessibility (e.g. <Loading>).
5
+ */
6
+ import type { JSX } from 'solid-js'
7
+ import { For, Show, splitProps } from 'solid-js'
8
+ import { cn } from '../../utilities/classNames'
9
+
10
+ const range = (n: number) => Array.from({ length: n }, (_, i) => i)
11
+
12
+ const SKELETON_CLASS = 'animate-pulse'
13
+ const BAR = 'rounded bg-ink-200'
14
+ const BAR_LIGHT = 'rounded bg-surface-overlay'
15
+ const CARD_BASE =
16
+ 'rounded-xl border border-surface-border bg-surface-raised'
17
+ const TABLE_HEAD = 'border-b border-surface-border'
18
+ const TABLE_DIVIDE = 'divide-y divide-surface-border'
19
+
20
+ /** Skeleton that matches Card layout: optional header, body with N lines. Compose to match your Card structure. */
21
+ export interface SkeletonCardProps {
22
+ /** Show a header bar (like Card.Header). Default true. */
23
+ header?: boolean
24
+ /** Number of body lines. Default 2. */
25
+ bodyLines?: number
26
+ /** Horizontal layout: image/avatar placeholder on left (like Card horizontal). */
27
+ horizontal?: boolean
28
+ class?: string
29
+ }
30
+
31
+ export function SkeletonCard(props: SkeletonCardProps): JSX.Element {
32
+ const [local] = splitProps(props, ['header', 'bodyLines', 'horizontal', 'class'])
33
+
34
+ const header = () => local.header !== false
35
+ const bodyLines = () => local.bodyLines ?? 2
36
+ const horizontal = () => local.horizontal === true
37
+ return (
38
+ <div
39
+ class={cn(
40
+ SKELETON_CLASS,
41
+ CARD_BASE,
42
+ horizontal() ? 'flex flex-row overflow-hidden' : 'flex flex-col',
43
+ local.class
44
+ )}
45
+ aria-hidden="true"
46
+ >
47
+ <Show when={horizontal()}>
48
+ <div class="h-24 w-24 shrink-0 rounded-l-xl bg-surface-overlay sm:h-28 sm:w-28" />
49
+ </Show>
50
+ <div class="min-w-0 flex-1 flex flex-col">
51
+ <Show when={header()}>
52
+ <div class="flex shrink-0 items-center justify-between gap-3 border-b border-surface-border px-6 py-4">
53
+ <div class={cn('h-5 w-32', BAR)} />
54
+ </div>
55
+ </Show>
56
+ <div class="flex flex-1 flex-col gap-2 p-6">
57
+ <For each={range(bodyLines())}>
58
+ {(i) => (
59
+ <div
60
+ class={cn('h-4 rounded', BAR_LIGHT)}
61
+ style={{ width: `${Math.max(50, 90 - (i + 1) * 15)}%` }}
62
+ />
63
+ )}
64
+ </For>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ )
69
+ }
70
+
71
+ /** Skeleton that matches Table layout: header row + N body rows × M cells. Compose to match your Table structure. */
72
+ export interface SkeletonTableProps {
73
+ /** Number of body rows. Default 5. */
74
+ rows?: number
75
+ /** Number of columns (header + each row). Default 4. */
76
+ columns?: number
77
+ class?: string
78
+ }
79
+
80
+ export function SkeletonTable(props: SkeletonTableProps): JSX.Element {
81
+ const [local] = splitProps(props, ['rows', 'columns', 'class'])
82
+
83
+ const rows = () => local.rows ?? 5
84
+ const columns = () => local.columns ?? 4
85
+ return (
86
+ <div class={cn(SKELETON_CLASS, 'overflow-hidden rounded-xl border border-surface-border bg-surface-raised', local.class)} aria-hidden="true">
87
+ <div class={cn('flex gap-4 px-6 py-3', TABLE_HEAD)}>
88
+ <For each={range(columns())}>
89
+ {() => <div class={cn('h-4 flex-1 rounded', BAR_LIGHT)} />}
90
+ </For>
91
+ </div>
92
+ <div class={TABLE_DIVIDE}>
93
+ <For each={range(rows())}>
94
+ {() => (
95
+ <div class="flex gap-4 px-6 py-4">
96
+ <For each={range(columns())}>
97
+ {() => <div class={cn('h-4 flex-1 rounded', BAR_LIGHT)} />}
98
+ </For>
99
+ </div>
100
+ )}
101
+ </For>
102
+ </div>
103
+ </div>
104
+ )
105
+ }
106
+
107
+ /** Skeleton that matches Section / PageHeading: title bar + optional description + content block. Compose to match your Section structure. */
108
+ export interface SkeletonSectionProps {
109
+ /** Show a description line under the title. Default true. */
110
+ description?: boolean
111
+ /** Show a content block below (e.g. form or card placeholder). Default true. */
112
+ content?: boolean
113
+ /** Content block lines. Default 3. */
114
+ contentLines?: number
115
+ class?: string
116
+ }
117
+
118
+ export function SkeletonSection(props: SkeletonSectionProps): JSX.Element {
119
+ const [local] = splitProps(props, ['description', 'content', 'contentLines', 'class'])
120
+
121
+ const description = () => local.description !== false
122
+ const content = () => local.content !== false
123
+ const contentLines = () => local.contentLines ?? 3
124
+ return (
125
+ <div class={cn(SKELETON_CLASS, 'space-y-4', local.class)} aria-hidden="true">
126
+ <div>
127
+ <div class={cn('h-7 w-48 rounded', BAR)} />
128
+ <Show when={description()}>
129
+ <div class={cn('mt-2 h-4 max-w-md rounded', BAR_LIGHT)} />
130
+ </Show>
131
+ </div>
132
+ <Show when={content()}>
133
+ <div class="rounded-xl border border-surface-border bg-surface-raised p-6">
134
+ <div class="flex flex-col gap-3">
135
+ <For each={range(contentLines())}>
136
+ {(i) => (
137
+ <div
138
+ class={cn('h-4 rounded', BAR_LIGHT)}
139
+ style={{ width: `${90 - (i + 1) * 10}%` }}
140
+ />
141
+ )}
142
+ </For>
143
+ </div>
144
+ </div>
145
+ </Show>
146
+ </div>
147
+ )
148
+ }
149
+
150
+ /** Skeleton block for a simple title + one line (e.g. PageHeading only, no section content). */
151
+ export interface SkeletonHeadingProps {
152
+ /** Show description line. Default true. */
153
+ description?: boolean
154
+ class?: string
155
+ }
156
+
157
+ export function SkeletonHeading(props: SkeletonHeadingProps): JSX.Element {
158
+ const [local] = splitProps(props, ['description', 'class'])
159
+
160
+ const description = () => local.description !== false
161
+ return (
162
+ <div class={cn(SKELETON_CLASS, local.class)} aria-hidden="true">
163
+ <div class={cn('h-8 w-48 rounded', BAR)} />
164
+ <Show when={description()}>
165
+ <div class={cn('mt-2 h-4 max-w-sm rounded', BAR_LIGHT)} />
166
+ </Show>
167
+ </div>
168
+ )
169
+ }
170
+
171
+ /** Skeleton for a form-like block: label lines + inputs + buttons. */
172
+ export interface SkeletonFormProps {
173
+ fields?: number
174
+ buttons?: number
175
+ class?: string
176
+ }
177
+
178
+ export function SkeletonForm(props: SkeletonFormProps): JSX.Element {
179
+ const [local] = splitProps(props, ['fields', 'buttons', 'class'])
180
+
181
+ const fields = () => local.fields ?? 2
182
+ const buttons = () => local.buttons ?? 2
183
+ return (
184
+ <div class={cn(SKELETON_CLASS, 'space-y-4 rounded-xl border border-surface-border bg-surface-raised p-6', local.class)} aria-hidden="true">
185
+ <For each={range(fields())}>
186
+ {() => (
187
+ <div class="space-y-1">
188
+ <div class={cn('h-4 w-32 rounded', BAR_LIGHT)} />
189
+ <div class={cn('h-10 w-full rounded-lg', BAR_LIGHT)} />
190
+ </div>
191
+ )}
192
+ </For>
193
+ <div class="flex gap-2 pt-2">
194
+ <For each={range(buttons())}>
195
+ {() => <div class={cn('h-10 w-24 rounded-lg', BAR)} />}
196
+ </For>
197
+ </div>
198
+ </div>
199
+ )
200
+ }
201
+
202
+ /** Skeleton for a sidebar nav block: section label + list of items. */
203
+ export interface SkeletonNavBlockProps {
204
+ items?: number
205
+ class?: string
206
+ }
207
+
208
+ export function SkeletonNavBlock(props: SkeletonNavBlockProps): JSX.Element {
209
+ const [local] = splitProps(props, ['items', 'class'])
210
+
211
+ const items = () => local.items ?? 4
212
+ return (
213
+ <div class={cn(SKELETON_CLASS, 'space-y-2', local.class)} aria-hidden="true">
214
+ <div class={cn('h-3 w-20 rounded', BAR)} />
215
+ <div class="space-y-0.5">
216
+ <For each={range(items())}>
217
+ {() => <div class={cn('h-9 rounded-lg', BAR_LIGHT)} />}
218
+ </For>
219
+ </div>
220
+ </div>
221
+ )
222
+ }