@taicode/common-web 1.0.4 → 1.1.0

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 (141) hide show
  1. package/output/catalyst/alert.d.ts +29 -0
  2. package/output/catalyst/alert.d.ts.map +1 -0
  3. package/output/catalyst/alert.jsx +55 -0
  4. package/output/catalyst/auth-layout.d.ts +5 -0
  5. package/output/catalyst/auth-layout.d.ts.map +1 -0
  6. package/{source/catalyst/auth-layout.tsx → output/catalyst/auth-layout.jsx} +3 -7
  7. package/output/catalyst/avatar.d.ts +15 -0
  8. package/output/catalyst/avatar.d.ts.map +1 -0
  9. package/output/catalyst/avatar.jsx +45 -0
  10. package/output/catalyst/badge.d.ts +34 -0
  11. package/output/catalyst/badge.d.ts.map +1 -0
  12. package/output/catalyst/badge.jsx +53 -0
  13. package/output/catalyst/button.d.ts +59 -0
  14. package/output/catalyst/button.d.ts.map +1 -0
  15. package/output/catalyst/button.jsx +187 -0
  16. package/output/catalyst/checkbox.d.ts +37 -0
  17. package/output/catalyst/checkbox.d.ts.map +1 -0
  18. package/output/catalyst/checkbox.jsx +105 -0
  19. package/output/catalyst/combobox.d.ts +20 -0
  20. package/output/catalyst/combobox.d.ts.map +1 -0
  21. package/output/catalyst/combobox.jsx +120 -0
  22. package/output/catalyst/description-list.d.ts +4 -0
  23. package/output/catalyst/description-list.d.ts.map +1 -0
  24. package/output/catalyst/description-list.jsx +24 -0
  25. package/output/catalyst/dialog.d.ts +29 -0
  26. package/output/catalyst/dialog.d.ts.map +1 -0
  27. package/output/catalyst/dialog.jsx +55 -0
  28. package/output/catalyst/divider.d.ts +4 -0
  29. package/output/catalyst/divider.d.ts.map +1 -0
  30. package/output/catalyst/divider.jsx +16 -0
  31. package/output/catalyst/dropdown.d.ts +33 -0
  32. package/output/catalyst/dropdown.d.ts.map +1 -0
  33. package/output/catalyst/dropdown.jsx +102 -0
  34. package/output/catalyst/fieldset.d.ts +22 -0
  35. package/output/catalyst/fieldset.d.ts.map +1 -0
  36. package/output/catalyst/fieldset.jsx +41 -0
  37. package/output/catalyst/heading.d.ts +7 -0
  38. package/output/catalyst/heading.d.ts.map +1 -0
  39. package/output/catalyst/heading.jsx +22 -0
  40. package/output/catalyst/input.d.ts +11 -0
  41. package/output/catalyst/input.d.ts.map +1 -0
  42. package/output/catalyst/input.jsx +73 -0
  43. package/output/catalyst/link.d.ts +12 -0
  44. package/output/catalyst/link.d.ts.map +1 -0
  45. package/output/catalyst/link.jsx +14 -0
  46. package/output/catalyst/listbox.d.ts +16 -0
  47. package/output/catalyst/listbox.d.ts.map +1 -0
  48. package/output/catalyst/listbox.jsx +120 -0
  49. package/output/catalyst/navbar.d.ts +15 -0
  50. package/output/catalyst/navbar.d.ts.map +1 -0
  51. package/output/catalyst/navbar.jsx +67 -0
  52. package/output/catalyst/pagination.d.ts +18 -0
  53. package/output/catalyst/pagination.d.ts.map +1 -0
  54. package/output/catalyst/pagination.jsx +52 -0
  55. package/output/catalyst/radio.d.ts +38 -0
  56. package/output/catalyst/radio.d.ts.map +1 -0
  57. package/output/catalyst/radio.jsx +103 -0
  58. package/output/catalyst/select.d.ts +6 -0
  59. package/output/catalyst/select.d.ts.map +1 -0
  60. package/output/catalyst/select.jsx +59 -0
  61. package/output/catalyst/sidebar-layout.d.ts +6 -0
  62. package/output/catalyst/sidebar-layout.d.ts.map +1 -0
  63. package/{source/catalyst/sidebar-layout.tsx → output/catalyst/sidebar-layout.jsx} +19 -43
  64. package/output/catalyst/sidebar.d.ts +19 -0
  65. package/output/catalyst/sidebar.d.ts.map +1 -0
  66. package/output/catalyst/sidebar.jsx +85 -0
  67. package/output/catalyst/stacked-layout.d.ts +6 -0
  68. package/output/catalyst/stacked-layout.d.ts.map +1 -0
  69. package/{source/catalyst/stacked-layout.tsx → output/catalyst/stacked-layout.jsx} +19 -43
  70. package/output/catalyst/switch.d.ts +37 -0
  71. package/output/catalyst/switch.d.ts.map +1 -0
  72. package/output/catalyst/switch.jsx +161 -0
  73. package/output/catalyst/table.d.ts +17 -0
  74. package/output/catalyst/table.d.ts.map +1 -0
  75. package/output/catalyst/table.jsx +68 -0
  76. package/output/catalyst/text.d.ts +6 -0
  77. package/output/catalyst/text.d.ts.map +1 -0
  78. package/output/catalyst/text.jsx +29 -0
  79. package/output/catalyst/textarea.d.ts +7 -0
  80. package/output/catalyst/textarea.d.ts.map +1 -0
  81. package/output/catalyst/textarea.jsx +49 -0
  82. package/output/helpers/service/index.d.ts +1 -0
  83. package/output/helpers/service/index.d.ts.map +1 -0
  84. package/output/helpers/service/index.js +1 -0
  85. package/output/helpers/service/service.d.ts +5 -0
  86. package/output/helpers/service/service.d.ts.map +1 -0
  87. package/output/helpers/service/service.js +2 -0
  88. package/output/helpers/side-cache/index.d.ts +2 -0
  89. package/output/helpers/side-cache/index.d.ts.map +1 -0
  90. package/output/helpers/side-cache/index.js +1 -0
  91. package/{source/utils/cache/aside.d.ts → output/helpers/side-cache/side-cache.d.ts} +2 -2
  92. package/output/helpers/side-cache/side-cache.d.ts.map +1 -0
  93. package/{source/utils/cache/aside.js → output/helpers/side-cache/side-cache.js} +12 -12
  94. package/output/helpers/side-cache/side-cache.test.d.ts +2 -0
  95. package/output/helpers/side-cache/side-cache.test.d.ts.map +1 -0
  96. package/output/helpers/side-cache/side-cache.test.js +89 -0
  97. package/output/helpers/use-observer/index.d.ts +2 -0
  98. package/output/helpers/use-observer/index.d.ts.map +1 -0
  99. package/output/helpers/use-observer/index.js +1 -0
  100. package/{source/hooks/mobx.d.ts → output/helpers/use-observer/use-observer.d.ts} +1 -1
  101. package/output/helpers/use-observer/use-observer.d.ts.map +1 -0
  102. package/output/helpers/use-observer/use-observer.test.d.ts +2 -0
  103. package/output/helpers/use-observer/use-observer.test.d.ts.map +1 -0
  104. package/output/helpers/use-observer/use-observer.test.jsx +134 -0
  105. package/package.json +25 -14
  106. package/source/catalyst/CHANGELOG.md +0 -136
  107. package/source/catalyst/README.md +0 -65
  108. package/source/catalyst/alert.tsx +0 -95
  109. package/source/catalyst/avatar.tsx +0 -84
  110. package/source/catalyst/badge.tsx +0 -82
  111. package/source/catalyst/button.tsx +0 -204
  112. package/source/catalyst/checkbox.tsx +0 -157
  113. package/source/catalyst/combobox.tsx +0 -188
  114. package/source/catalyst/description-list.tsx +0 -37
  115. package/source/catalyst/dialog.tsx +0 -86
  116. package/source/catalyst/divider.tsx +0 -20
  117. package/source/catalyst/dropdown.tsx +0 -183
  118. package/source/catalyst/fieldset.tsx +0 -91
  119. package/source/catalyst/heading.tsx +0 -27
  120. package/source/catalyst/input.tsx +0 -94
  121. package/source/catalyst/link.tsx +0 -21
  122. package/source/catalyst/listbox.tsx +0 -177
  123. package/source/catalyst/navbar.tsx +0 -96
  124. package/source/catalyst/pagination.tsx +0 -98
  125. package/source/catalyst/radio.tsx +0 -142
  126. package/source/catalyst/select.tsx +0 -68
  127. package/source/catalyst/sidebar.tsx +0 -142
  128. package/source/catalyst/switch.tsx +0 -195
  129. package/source/catalyst/table.tsx +0 -124
  130. package/source/catalyst/text.tsx +0 -40
  131. package/source/catalyst/textarea.tsx +0 -54
  132. package/source/hooks/mobx.d.ts.map +0 -1
  133. package/source/hooks/mobx.ts +0 -24
  134. package/source/utils/cache/aside.d.ts.map +0 -1
  135. package/source/utils/cache/aside.ts +0 -39
  136. package/source/utils/cache/index.d.ts +0 -2
  137. package/source/utils/cache/index.d.ts.map +0 -1
  138. package/source/utils/cache/index.js +0 -1
  139. package/source/utils/cache/index.ts +0 -1
  140. package/tsconfig.json +0 -106
  141. /package/{source/hooks/mobx.js → output/helpers/use-observer/use-observer.js} +0 -0
@@ -1,142 +0,0 @@
1
- import * as Headless from '@headlessui/react'
2
- import clsx from 'clsx'
3
-
4
- export function RadioGroup({
5
- className,
6
- ...props
7
- }: { className?: string } & Omit<Headless.RadioGroupProps, 'as' | 'className'>) {
8
- return (
9
- <Headless.RadioGroup
10
- data-slot="control"
11
- {...props}
12
- className={clsx(
13
- className,
14
- // Basic groups
15
- 'space-y-3 **:data-[slot=label]:font-normal',
16
- // With descriptions
17
- 'has-data-[slot=description]:space-y-6 has-data-[slot=description]:**:data-[slot=label]:font-medium'
18
- )}
19
- />
20
- )
21
- }
22
-
23
- export function RadioField({
24
- className,
25
- ...props
26
- }: { className?: string } & Omit<Headless.FieldProps, 'as' | 'className'>) {
27
- return (
28
- <Headless.Field
29
- data-slot="field"
30
- {...props}
31
- className={clsx(
32
- className,
33
- // Base layout
34
- 'grid grid-cols-[1.125rem_1fr] gap-x-4 gap-y-1 sm:grid-cols-[1rem_1fr]',
35
- // Control layout
36
- '*:data-[slot=control]:col-start-1 *:data-[slot=control]:row-start-1 *:data-[slot=control]:mt-0.75 sm:*:data-[slot=control]:mt-1',
37
- // Label layout
38
- '*:data-[slot=label]:col-start-2 *:data-[slot=label]:row-start-1',
39
- // Description layout
40
- '*:data-[slot=description]:col-start-2 *:data-[slot=description]:row-start-2',
41
- // With description
42
- 'has-data-[slot=description]:**:data-[slot=label]:font-medium'
43
- )}
44
- />
45
- )
46
- }
47
-
48
- const base = [
49
- // Basic layout
50
- 'relative isolate flex size-4.75 shrink-0 rounded-full sm:size-4.25',
51
- // Background color + shadow applied to inset pseudo element, so shadow blends with border in light mode
52
- 'before:absolute before:inset-0 before:-z-10 before:rounded-full before:bg-white before:shadow-sm',
53
- // Background color when checked
54
- 'group-data-checked:before:bg-(--radio-checked-bg)',
55
- // Background color is moved to control and shadow is removed in dark mode so hide `before` pseudo
56
- 'dark:before:hidden',
57
- // Background color applied to control in dark mode
58
- 'dark:bg-white/5 dark:group-data-checked:bg-(--radio-checked-bg)',
59
- // Border
60
- 'border border-zinc-950/15 group-data-checked:border-transparent group-data-hover:group-data-checked:border-transparent group-data-hover:border-zinc-950/30 group-data-checked:bg-(--radio-checked-border)',
61
- 'dark:border-white/15 dark:group-data-checked:border-white/5 dark:group-data-hover:group-data-checked:border-white/5 dark:group-data-hover:border-white/30',
62
- // Inner highlight shadow
63
- 'after:absolute after:inset-0 after:rounded-full after:shadow-[inset_0_1px_--theme(--color-white/15%)]',
64
- 'dark:after:-inset-px dark:after:hidden dark:after:rounded-full dark:group-data-checked:after:block',
65
- // Indicator color (light mode)
66
- '[--radio-indicator:transparent] group-data-checked:[--radio-indicator:var(--radio-checked-indicator)] group-data-hover:group-data-checked:[--radio-indicator:var(--radio-checked-indicator)] group-data-hover:[--radio-indicator:var(--color-zinc-900)]/10',
67
- // Indicator color (dark mode)
68
- 'dark:group-data-hover:group-data-checked:[--radio-indicator:var(--radio-checked-indicator)] dark:group-data-hover:[--radio-indicator:var(--color-zinc-700)]',
69
- // Focus ring
70
- 'group-data-focus:outline group-data-focus:outline-2 group-data-focus:outline-offset-2 group-data-focus:outline-blue-500',
71
- // Disabled state
72
- 'group-data-disabled:opacity-50',
73
- 'group-data-disabled:border-zinc-950/25 group-data-disabled:bg-zinc-950/5 group-data-disabled:[--radio-checked-indicator:var(--color-zinc-950)]/50 group-data-disabled:before:bg-transparent',
74
- 'dark:group-data-disabled:border-white/20 dark:group-data-disabled:bg-white/2.5 dark:group-data-disabled:[--radio-checked-indicator:var(--color-white)]/50 dark:group-data-checked:group-data-disabled:after:hidden',
75
- ]
76
-
77
- const colors = {
78
- 'dark/zinc': [
79
- '[--radio-checked-bg:var(--color-zinc-900)] [--radio-checked-border:var(--color-zinc-950)]/90 [--radio-checked-indicator:var(--color-white)]',
80
- 'dark:[--radio-checked-bg:var(--color-zinc-600)]',
81
- ],
82
- 'dark/white': [
83
- '[--radio-checked-bg:var(--color-zinc-900)] [--radio-checked-border:var(--color-zinc-950)]/90 [--radio-checked-indicator:var(--color-white)]',
84
- 'dark:[--radio-checked-bg:var(--color-white)] dark:[--radio-checked-border:var(--color-zinc-950)]/15 dark:[--radio-checked-indicator:var(--color-zinc-900)]',
85
- ],
86
- white:
87
- '[--radio-checked-bg:var(--color-white)] [--radio-checked-border:var(--color-zinc-950)]/15 [--radio-checked-indicator:var(--color-zinc-900)]',
88
- dark: '[--radio-checked-bg:var(--color-zinc-900)] [--radio-checked-border:var(--color-zinc-950)]/90 [--radio-checked-indicator:var(--color-white)]',
89
- zinc: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-zinc-600)] [--radio-checked-border:var(--color-zinc-700)]/90',
90
- red: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-red-600)] [--radio-checked-border:var(--color-red-700)]/90',
91
- orange:
92
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-orange-500)] [--radio-checked-border:var(--color-orange-600)]/90',
93
- amber:
94
- '[--radio-checked-bg:var(--color-amber-400)] [--radio-checked-border:var(--color-amber-500)]/80 [--radio-checked-indicator:var(--color-amber-950)]',
95
- yellow:
96
- '[--radio-checked-bg:var(--color-yellow-300)] [--radio-checked-border:var(--color-yellow-400)]/80 [--radio-checked-indicator:var(--color-yellow-950)]',
97
- lime: '[--radio-checked-bg:var(--color-lime-300)] [--radio-checked-border:var(--color-lime-400)]/80 [--radio-checked-indicator:var(--color-lime-950)]',
98
- green:
99
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-green-600)] [--radio-checked-border:var(--color-green-700)]/90',
100
- emerald:
101
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-emerald-600)] [--radio-checked-border:var(--color-emerald-700)]/90',
102
- teal: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-teal-600)] [--radio-checked-border:var(--color-teal-700)]/90',
103
- cyan: '[--radio-checked-bg:var(--color-cyan-300)] [--radio-checked-border:var(--color-cyan-400)]/80 [--radio-checked-indicator:var(--color-cyan-950)]',
104
- sky: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-sky-500)] [--radio-checked-border:var(--color-sky-600)]/80',
105
- blue: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-blue-600)] [--radio-checked-border:var(--color-blue-700)]/90',
106
- indigo:
107
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-indigo-500)] [--radio-checked-border:var(--color-indigo-600)]/90',
108
- violet:
109
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-violet-500)] [--radio-checked-border:var(--color-violet-600)]/90',
110
- purple:
111
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-purple-500)] [--radio-checked-border:var(--color-purple-600)]/90',
112
- fuchsia:
113
- '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-fuchsia-500)] [--radio-checked-border:var(--color-fuchsia-600)]/90',
114
- pink: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-pink-500)] [--radio-checked-border:var(--color-pink-600)]/90',
115
- rose: '[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-rose-500)] [--radio-checked-border:var(--color-rose-600)]/90',
116
- }
117
-
118
- type Color = keyof typeof colors
119
-
120
- export function Radio({
121
- color = 'dark/zinc',
122
- className,
123
- ...props
124
- }: { color?: Color; className?: string } & Omit<Headless.RadioProps, 'as' | 'className' | 'children'>) {
125
- return (
126
- <Headless.Radio
127
- data-slot="control"
128
- {...props}
129
- className={clsx(className, 'group inline-flex focus:outline-hidden')}
130
- >
131
- <span className={clsx([base, colors[color]])}>
132
- <span
133
- className={clsx(
134
- 'size-full rounded-full border-[4.5px] border-transparent bg-(--radio-indicator) bg-clip-padding',
135
- // Forced colors mode
136
- 'forced-colors:border-[Canvas] forced-colors:group-data-checked:border-[Highlight]'
137
- )}
138
- />
139
- </span>
140
- </Headless.Radio>
141
- )
142
- }
@@ -1,68 +0,0 @@
1
- import * as Headless from '@headlessui/react'
2
- import clsx from 'clsx'
3
- import React, { forwardRef } from 'react'
4
-
5
- export const Select = forwardRef(function Select(
6
- { className, multiple, ...props }: { className?: string } & Omit<Headless.SelectProps, 'as' | 'className'>,
7
- ref: React.ForwardedRef<HTMLSelectElement>
8
- ) {
9
- return (
10
- <span
11
- data-slot="control"
12
- className={clsx([
13
- className,
14
- // Basic layout
15
- 'group relative block w-full',
16
- // Background color + shadow applied to inset pseudo element, so shadow blends with border in light mode
17
- 'before:absolute before:inset-px before:rounded-[calc(var(--radius-lg)-1px)] before:bg-white before:shadow-sm',
18
- // Background color is moved to control and shadow is removed in dark mode so hide `before` pseudo
19
- 'dark:before:hidden',
20
- // Focus ring
21
- 'after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-transparent after:ring-inset has-data-focus:after:ring-2 has-data-focus:after:ring-blue-500',
22
- // Disabled state
23
- 'has-data-disabled:opacity-50 has-data-disabled:before:bg-zinc-950/5 has-data-disabled:before:shadow-none',
24
- ])}
25
- >
26
- <Headless.Select
27
- ref={ref}
28
- multiple={multiple}
29
- {...props}
30
- className={clsx([
31
- // Basic layout
32
- 'relative block w-full appearance-none rounded-lg py-[calc(--spacing(2.5)-1px)] sm:py-[calc(--spacing(1.5)-1px)]',
33
- // Horizontal padding
34
- multiple
35
- ? 'px-[calc(--spacing(3.5)-1px)] sm:px-[calc(--spacing(3)-1px)]'
36
- : 'pr-[calc(--spacing(10)-1px)] pl-[calc(--spacing(3.5)-1px)] sm:pr-[calc(--spacing(9)-1px)] sm:pl-[calc(--spacing(3)-1px)]',
37
- // Options (multi-select)
38
- '[&_optgroup]:font-semibold',
39
- // Typography
40
- 'text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white dark:*:text-white',
41
- // Border
42
- 'border border-zinc-950/10 data-hover:border-zinc-950/20 dark:border-white/10 dark:data-hover:border-white/20',
43
- // Background color
44
- 'bg-transparent dark:bg-white/5 dark:*:bg-zinc-800',
45
- // Hide default focus styles
46
- 'focus:outline-hidden',
47
- // Invalid state
48
- 'data-invalid:border-red-500 data-invalid:data-hover:border-red-500 dark:data-invalid:border-red-600 dark:data-invalid:data-hover:border-red-600',
49
- // Disabled state
50
- 'data-disabled:border-zinc-950/20 data-disabled:opacity-100 dark:data-disabled:border-white/15 dark:data-disabled:bg-white/2.5 dark:data-hover:data-disabled:border-white/15',
51
- ])}
52
- />
53
- {!multiple && (
54
- <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
55
- <svg
56
- className="size-5 stroke-zinc-500 group-has-data-disabled:stroke-zinc-600 sm:size-4 dark:stroke-zinc-400 forced-colors:stroke-[CanvasText]"
57
- viewBox="0 0 16 16"
58
- aria-hidden="true"
59
- fill="none"
60
- >
61
- <path d="M5.75 10.75L8 13L10.25 10.75" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
62
- <path d="M10.25 5.25L8 3L5.75 5.25" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
63
- </svg>
64
- </span>
65
- )}
66
- </span>
67
- )
68
- })
@@ -1,142 +0,0 @@
1
- 'use client'
2
-
3
- import * as Headless from '@headlessui/react'
4
- import clsx from 'clsx'
5
- import { LayoutGroup, motion } from 'framer-motion'
6
- import React, { forwardRef, useId } from 'react'
7
- import { TouchTarget } from './button'
8
- import { Link } from './link'
9
-
10
- export function Sidebar({ className, ...props }: React.ComponentPropsWithoutRef<'nav'>) {
11
- return <nav {...props} className={clsx(className, 'flex h-full min-h-0 flex-col')} />
12
- }
13
-
14
- export function SidebarHeader({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
15
- return (
16
- <div
17
- {...props}
18
- className={clsx(
19
- className,
20
- 'flex flex-col border-b border-zinc-950/5 p-4 dark:border-white/5 [&>[data-slot=section]+[data-slot=section]]:mt-2.5'
21
- )}
22
- />
23
- )
24
- }
25
-
26
- export function SidebarBody({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
27
- return (
28
- <div
29
- {...props}
30
- className={clsx(
31
- className,
32
- 'flex flex-1 flex-col overflow-y-auto p-4 [&>[data-slot=section]+[data-slot=section]]:mt-8'
33
- )}
34
- />
35
- )
36
- }
37
-
38
- export function SidebarFooter({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
39
- return (
40
- <div
41
- {...props}
42
- className={clsx(
43
- className,
44
- 'flex flex-col border-t border-zinc-950/5 p-4 dark:border-white/5 [&>[data-slot=section]+[data-slot=section]]:mt-2.5'
45
- )}
46
- />
47
- )
48
- }
49
-
50
- export function SidebarSection({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
51
- let id = useId()
52
-
53
- return (
54
- <LayoutGroup id={id}>
55
- <div {...props} data-slot="section" className={clsx(className, 'flex flex-col gap-0.5')} />
56
- </LayoutGroup>
57
- )
58
- }
59
-
60
- export function SidebarDivider({ className, ...props }: React.ComponentPropsWithoutRef<'hr'>) {
61
- return <hr {...props} className={clsx(className, 'my-4 border-t border-zinc-950/5 lg:-mx-4 dark:border-white/5')} />
62
- }
63
-
64
- export function SidebarSpacer({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
65
- return <div aria-hidden="true" {...props} className={clsx(className, 'mt-8 flex-1')} />
66
- }
67
-
68
- export function SidebarHeading({ className, ...props }: React.ComponentPropsWithoutRef<'h3'>) {
69
- return (
70
- <h3 {...props} className={clsx(className, 'mb-1 px-2 text-xs/6 font-medium text-zinc-500 dark:text-zinc-400')} />
71
- )
72
- }
73
-
74
- export const SidebarItem = forwardRef(function SidebarItem(
75
- {
76
- current,
77
- className,
78
- children,
79
- ...props
80
- }: { current?: boolean; className?: string; children: React.ReactNode } & (
81
- | Omit<Headless.ButtonProps, 'as' | 'className'>
82
- | Omit<Headless.ButtonProps<typeof Link>, 'as' | 'className'>
83
- ),
84
- ref: React.ForwardedRef<HTMLAnchorElement | HTMLButtonElement>
85
- ) {
86
- let classes = clsx(
87
- // Base
88
- 'flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-base/6 font-medium text-zinc-950 sm:py-2 sm:text-sm/5',
89
- // Leading icon/icon-only
90
- '*:data-[slot=icon]:size-6 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:fill-zinc-500 sm:*:data-[slot=icon]:size-5',
91
- // Trailing icon (down chevron or similar)
92
- '*:last:data-[slot=icon]:ml-auto *:last:data-[slot=icon]:size-5 sm:*:last:data-[slot=icon]:size-4',
93
- // Avatar
94
- '*:data-[slot=avatar]:-m-0.5 *:data-[slot=avatar]:size-7 sm:*:data-[slot=avatar]:size-6',
95
- // Hover
96
- 'data-hover:bg-zinc-950/5 data-hover:*:data-[slot=icon]:fill-zinc-950',
97
- // Active
98
- 'data-active:bg-zinc-950/5 data-active:*:data-[slot=icon]:fill-zinc-950',
99
- // Current
100
- 'data-current:*:data-[slot=icon]:fill-zinc-950',
101
- // Dark mode
102
- 'dark:text-white dark:*:data-[slot=icon]:fill-zinc-400',
103
- 'dark:data-hover:bg-white/5 dark:data-hover:*:data-[slot=icon]:fill-white',
104
- 'dark:data-active:bg-white/5 dark:data-active:*:data-[slot=icon]:fill-white',
105
- 'dark:data-current:*:data-[slot=icon]:fill-white'
106
- )
107
-
108
- return (
109
- <span className={clsx(className, 'relative')}>
110
- {current && (
111
- <motion.span
112
- layoutId="current-indicator"
113
- className="absolute inset-y-2 -left-4 w-0.5 rounded-full bg-zinc-950 dark:bg-white"
114
- />
115
- )}
116
- {'href' in props ? (
117
- <Headless.CloseButton
118
- as={Link}
119
- {...props}
120
- className={classes}
121
- data-current={current ? 'true' : undefined}
122
- ref={ref}
123
- >
124
- <TouchTarget>{children}</TouchTarget>
125
- </Headless.CloseButton>
126
- ) : (
127
- <Headless.Button
128
- {...props}
129
- className={clsx('cursor-default', classes)}
130
- data-current={current ? 'true' : undefined}
131
- ref={ref}
132
- >
133
- <TouchTarget>{children}</TouchTarget>
134
- </Headless.Button>
135
- )}
136
- </span>
137
- )
138
- })
139
-
140
- export function SidebarLabel({ className, ...props }: React.ComponentPropsWithoutRef<'span'>) {
141
- return <span {...props} className={clsx(className, 'truncate')} />
142
- }
@@ -1,195 +0,0 @@
1
- import * as Headless from '@headlessui/react'
2
- import clsx from 'clsx'
3
- import type React from 'react'
4
-
5
- export function SwitchGroup({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
6
- return (
7
- <div
8
- data-slot="control"
9
- {...props}
10
- className={clsx(
11
- className,
12
- // Basic groups
13
- 'space-y-3 **:data-[slot=label]:font-normal',
14
- // With descriptions
15
- 'has-data-[slot=description]:space-y-6 has-data-[slot=description]:**:data-[slot=label]:font-medium'
16
- )}
17
- />
18
- )
19
- }
20
-
21
- export function SwitchField({
22
- className,
23
- ...props
24
- }: { className?: string } & Omit<Headless.FieldProps, 'as' | 'className'>) {
25
- return (
26
- <Headless.Field
27
- data-slot="field"
28
- {...props}
29
- className={clsx(
30
- className,
31
- // Base layout
32
- 'grid grid-cols-[1fr_auto] gap-x-8 gap-y-1 sm:grid-cols-[1fr_auto]',
33
- // Control layout
34
- '*:data-[slot=control]:col-start-2 *:data-[slot=control]:self-start sm:*:data-[slot=control]:mt-0.5',
35
- // Label layout
36
- '*:data-[slot=label]:col-start-1 *:data-[slot=label]:row-start-1',
37
- // Description layout
38
- '*:data-[slot=description]:col-start-1 *:data-[slot=description]:row-start-2',
39
- // With description
40
- 'has-data-[slot=description]:**:data-[slot=label]:font-medium'
41
- )}
42
- />
43
- )
44
- }
45
-
46
- const colors = {
47
- 'dark/zinc': [
48
- '[--switch-bg-ring:var(--color-zinc-950)]/90 [--switch-bg:var(--color-zinc-900)] dark:[--switch-bg-ring:transparent] dark:[--switch-bg:var(--color-white)]/25',
49
- '[--switch-ring:var(--color-zinc-950)]/90 [--switch-shadow:var(--color-black)]/10 [--switch:white] dark:[--switch-ring:var(--color-zinc-700)]/90',
50
- ],
51
- 'dark/white': [
52
- '[--switch-bg-ring:var(--color-zinc-950)]/90 [--switch-bg:var(--color-zinc-900)] dark:[--switch-bg-ring:transparent] dark:[--switch-bg:var(--color-white)]',
53
- '[--switch-ring:var(--color-zinc-950)]/90 [--switch-shadow:var(--color-black)]/10 [--switch:white] dark:[--switch-ring:transparent] dark:[--switch:var(--color-zinc-900)]',
54
- ],
55
- dark: [
56
- '[--switch-bg-ring:var(--color-zinc-950)]/90 [--switch-bg:var(--color-zinc-900)] dark:[--switch-bg-ring:var(--color-white)]/15',
57
- '[--switch-ring:var(--color-zinc-950)]/90 [--switch-shadow:var(--color-black)]/10 [--switch:white]',
58
- ],
59
- zinc: [
60
- '[--switch-bg-ring:var(--color-zinc-700)]/90 [--switch-bg:var(--color-zinc-600)] dark:[--switch-bg-ring:transparent]',
61
- '[--switch-shadow:var(--color-black)]/10 [--switch:white] [--switch-ring:var(--color-zinc-700)]/90',
62
- ],
63
- white: [
64
- '[--switch-bg-ring:var(--color-black)]/15 [--switch-bg:white] dark:[--switch-bg-ring:transparent]',
65
- '[--switch-shadow:var(--color-black)]/10 [--switch-ring:transparent] [--switch:var(--color-zinc-950)]',
66
- ],
67
- red: [
68
- '[--switch-bg-ring:var(--color-red-700)]/90 [--switch-bg:var(--color-red-600)] dark:[--switch-bg-ring:transparent]',
69
- '[--switch:white] [--switch-ring:var(--color-red-700)]/90 [--switch-shadow:var(--color-red-900)]/20',
70
- ],
71
- orange: [
72
- '[--switch-bg-ring:var(--color-orange-600)]/90 [--switch-bg:var(--color-orange-500)] dark:[--switch-bg-ring:transparent]',
73
- '[--switch:white] [--switch-ring:var(--color-orange-600)]/90 [--switch-shadow:var(--color-orange-900)]/20',
74
- ],
75
- amber: [
76
- '[--switch-bg-ring:var(--color-amber-500)]/80 [--switch-bg:var(--color-amber-400)] dark:[--switch-bg-ring:transparent]',
77
- '[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-amber-950)]',
78
- ],
79
- yellow: [
80
- '[--switch-bg-ring:var(--color-yellow-400)]/80 [--switch-bg:var(--color-yellow-300)] dark:[--switch-bg-ring:transparent]',
81
- '[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-yellow-950)]',
82
- ],
83
- lime: [
84
- '[--switch-bg-ring:var(--color-lime-400)]/80 [--switch-bg:var(--color-lime-300)] dark:[--switch-bg-ring:transparent]',
85
- '[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-lime-950)]',
86
- ],
87
- green: [
88
- '[--switch-bg-ring:var(--color-green-700)]/90 [--switch-bg:var(--color-green-600)] dark:[--switch-bg-ring:transparent]',
89
- '[--switch:white] [--switch-ring:var(--color-green-700)]/90 [--switch-shadow:var(--color-green-900)]/20',
90
- ],
91
- emerald: [
92
- '[--switch-bg-ring:var(--color-emerald-600)]/90 [--switch-bg:var(--color-emerald-500)] dark:[--switch-bg-ring:transparent]',
93
- '[--switch:white] [--switch-ring:var(--color-emerald-600)]/90 [--switch-shadow:var(--color-emerald-900)]/20',
94
- ],
95
- teal: [
96
- '[--switch-bg-ring:var(--color-teal-700)]/90 [--switch-bg:var(--color-teal-600)] dark:[--switch-bg-ring:transparent]',
97
- '[--switch:white] [--switch-ring:var(--color-teal-700)]/90 [--switch-shadow:var(--color-teal-900)]/20',
98
- ],
99
- cyan: [
100
- '[--switch-bg-ring:var(--color-cyan-400)]/80 [--switch-bg:var(--color-cyan-300)] dark:[--switch-bg-ring:transparent]',
101
- '[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-cyan-950)]',
102
- ],
103
- sky: [
104
- '[--switch-bg-ring:var(--color-sky-600)]/80 [--switch-bg:var(--color-sky-500)] dark:[--switch-bg-ring:transparent]',
105
- '[--switch:white] [--switch-ring:var(--color-sky-600)]/80 [--switch-shadow:var(--color-sky-900)]/20',
106
- ],
107
- blue: [
108
- '[--switch-bg-ring:var(--color-blue-700)]/90 [--switch-bg:var(--color-blue-600)] dark:[--switch-bg-ring:transparent]',
109
- '[--switch:white] [--switch-ring:var(--color-blue-700)]/90 [--switch-shadow:var(--color-blue-900)]/20',
110
- ],
111
- indigo: [
112
- '[--switch-bg-ring:var(--color-indigo-600)]/90 [--switch-bg:var(--color-indigo-500)] dark:[--switch-bg-ring:transparent]',
113
- '[--switch:white] [--switch-ring:var(--color-indigo-600)]/90 [--switch-shadow:var(--color-indigo-900)]/20',
114
- ],
115
- violet: [
116
- '[--switch-bg-ring:var(--color-violet-600)]/90 [--switch-bg:var(--color-violet-500)] dark:[--switch-bg-ring:transparent]',
117
- '[--switch:white] [--switch-ring:var(--color-violet-600)]/90 [--switch-shadow:var(--color-violet-900)]/20',
118
- ],
119
- purple: [
120
- '[--switch-bg-ring:var(--color-purple-600)]/90 [--switch-bg:var(--color-purple-500)] dark:[--switch-bg-ring:transparent]',
121
- '[--switch:white] [--switch-ring:var(--color-purple-600)]/90 [--switch-shadow:var(--color-purple-900)]/20',
122
- ],
123
- fuchsia: [
124
- '[--switch-bg-ring:var(--color-fuchsia-600)]/90 [--switch-bg:var(--color-fuchsia-500)] dark:[--switch-bg-ring:transparent]',
125
- '[--switch:white] [--switch-ring:var(--color-fuchsia-600)]/90 [--switch-shadow:var(--color-fuchsia-900)]/20',
126
- ],
127
- pink: [
128
- '[--switch-bg-ring:var(--color-pink-600)]/90 [--switch-bg:var(--color-pink-500)] dark:[--switch-bg-ring:transparent]',
129
- '[--switch:white] [--switch-ring:var(--color-pink-600)]/90 [--switch-shadow:var(--color-pink-900)]/20',
130
- ],
131
- rose: [
132
- '[--switch-bg-ring:var(--color-rose-600)]/90 [--switch-bg:var(--color-rose-500)] dark:[--switch-bg-ring:transparent]',
133
- '[--switch:white] [--switch-ring:var(--color-rose-600)]/90 [--switch-shadow:var(--color-rose-900)]/20',
134
- ],
135
- }
136
-
137
- type Color = keyof typeof colors
138
-
139
- export function Switch({
140
- color = 'dark/zinc',
141
- className,
142
- ...props
143
- }: {
144
- color?: Color
145
- className?: string
146
- } & Omit<Headless.SwitchProps, 'as' | 'className' | 'children'>) {
147
- return (
148
- <Headless.Switch
149
- data-slot="control"
150
- {...props}
151
- className={clsx(
152
- className,
153
- // Base styles
154
- 'group relative isolate inline-flex h-6 w-10 cursor-default rounded-full p-[3px] sm:h-5 sm:w-8',
155
- // Transitions
156
- 'transition duration-0 ease-in-out data-changing:duration-200',
157
- // Outline and background color in forced-colors mode so switch is still visible
158
- 'forced-colors:outline forced-colors:[--switch-bg:Highlight] dark:forced-colors:[--switch-bg:Highlight]',
159
- // Unchecked
160
- 'bg-zinc-200 ring-1 ring-black/5 ring-inset dark:bg-white/5 dark:ring-white/15',
161
- // Checked
162
- 'data-checked:bg-(--switch-bg) data-checked:ring-(--switch-bg-ring) dark:data-checked:bg-(--switch-bg) dark:data-checked:ring-(--switch-bg-ring)',
163
- // Focus
164
- 'focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-blue-500',
165
- // Hover
166
- 'data-hover:ring-black/15 data-hover:data-checked:ring-(--switch-bg-ring)',
167
- 'dark:data-hover:ring-white/25 dark:data-hover:data-checked:ring-(--switch-bg-ring)',
168
- // Disabled
169
- 'data-disabled:bg-zinc-200 data-disabled:opacity-50 data-disabled:data-checked:bg-zinc-200 data-disabled:data-checked:ring-black/5',
170
- 'dark:data-disabled:bg-white/15 dark:data-disabled:data-checked:bg-white/15 dark:data-disabled:data-checked:ring-white/15',
171
- // Color specific styles
172
- colors[color]
173
- )}
174
- >
175
- <span
176
- aria-hidden="true"
177
- className={clsx(
178
- // Basic layout
179
- 'pointer-events-none relative inline-block size-4.5 rounded-full sm:size-3.5',
180
- // Transition
181
- 'translate-x-0 transition duration-200 ease-in-out',
182
- // Invisible border so the switch is still visible in forced-colors mode
183
- 'border border-transparent',
184
- // Unchecked
185
- 'bg-white shadow-sm ring-1 ring-black/5',
186
- // Checked
187
- 'group-data-checked:bg-(--switch) group-data-checked:shadow-(--switch-shadow) group-data-checked:ring-(--switch-ring)',
188
- 'group-data-checked:translate-x-4 sm:group-data-checked:translate-x-3',
189
- // Disabled
190
- 'group-data-checked:group-data-disabled:bg-white group-data-checked:group-data-disabled:shadow-sm group-data-checked:group-data-disabled:ring-black/5'
191
- )}
192
- />
193
- </Headless.Switch>
194
- )
195
- }
@@ -1,124 +0,0 @@
1
- 'use client'
2
-
3
- import clsx from 'clsx'
4
- import type React from 'react'
5
- import { createContext, useContext, useState } from 'react'
6
- import { Link } from './link'
7
-
8
- const TableContext = createContext<{ bleed: boolean; dense: boolean; grid: boolean; striped: boolean }>({
9
- bleed: false,
10
- dense: false,
11
- grid: false,
12
- striped: false,
13
- })
14
-
15
- export function Table({
16
- bleed = false,
17
- dense = false,
18
- grid = false,
19
- striped = false,
20
- className,
21
- children,
22
- ...props
23
- }: { bleed?: boolean; dense?: boolean; grid?: boolean; striped?: boolean } & React.ComponentPropsWithoutRef<'div'>) {
24
- return (
25
- <TableContext.Provider value={{ bleed, dense, grid, striped } as React.ContextType<typeof TableContext>}>
26
- <div className="flow-root">
27
- <div {...props} className={clsx(className, '-mx-(--gutter) overflow-x-auto whitespace-nowrap')}>
28
- <div className={clsx('inline-block min-w-full align-middle', !bleed && 'sm:px-(--gutter)')}>
29
- <table className="min-w-full text-left text-sm/6 text-zinc-950 dark:text-white">{children}</table>
30
- </div>
31
- </div>
32
- </div>
33
- </TableContext.Provider>
34
- )
35
- }
36
-
37
- export function TableHead({ className, ...props }: React.ComponentPropsWithoutRef<'thead'>) {
38
- return <thead {...props} className={clsx(className, 'text-zinc-500 dark:text-zinc-400')} />
39
- }
40
-
41
- export function TableBody(props: React.ComponentPropsWithoutRef<'tbody'>) {
42
- return <tbody {...props} />
43
- }
44
-
45
- const TableRowContext = createContext<{ href?: string; target?: string; title?: string }>({
46
- href: undefined,
47
- target: undefined,
48
- title: undefined,
49
- })
50
-
51
- export function TableRow({
52
- href,
53
- target,
54
- title,
55
- className,
56
- ...props
57
- }: { href?: string; target?: string; title?: string } & React.ComponentPropsWithoutRef<'tr'>) {
58
- let { striped } = useContext(TableContext)
59
-
60
- return (
61
- <TableRowContext.Provider value={{ href, target, title } as React.ContextType<typeof TableRowContext>}>
62
- <tr
63
- {...props}
64
- className={clsx(
65
- className,
66
- href &&
67
- 'has-[[data-row-link][data-focus]]:outline-2 has-[[data-row-link][data-focus]]:-outline-offset-2 has-[[data-row-link][data-focus]]:outline-blue-500 dark:focus-within:bg-white/2.5',
68
- striped && 'even:bg-zinc-950/2.5 dark:even:bg-white/2.5',
69
- href && striped && 'hover:bg-zinc-950/5 dark:hover:bg-white/5',
70
- href && !striped && 'hover:bg-zinc-950/2.5 dark:hover:bg-white/2.5'
71
- )}
72
- />
73
- </TableRowContext.Provider>
74
- )
75
- }
76
-
77
- export function TableHeader({ className, ...props }: React.ComponentPropsWithoutRef<'th'>) {
78
- let { bleed, grid } = useContext(TableContext)
79
-
80
- return (
81
- <th
82
- {...props}
83
- className={clsx(
84
- className,
85
- 'border-b border-b-zinc-950/10 px-4 py-2 font-medium first:pl-(--gutter,--spacing(2)) last:pr-(--gutter,--spacing(2)) dark:border-b-white/10',
86
- grid && 'border-l border-l-zinc-950/5 first:border-l-0 dark:border-l-white/5',
87
- !bleed && 'sm:first:pl-1 sm:last:pr-1'
88
- )}
89
- />
90
- )
91
- }
92
-
93
- export function TableCell({ className, children, ...props }: React.ComponentPropsWithoutRef<'td'>) {
94
- let { bleed, dense, grid, striped } = useContext(TableContext)
95
- let { href, target, title } = useContext(TableRowContext)
96
- let [cellRef, setCellRef] = useState<HTMLElement | null>(null)
97
-
98
- return (
99
- <td
100
- ref={href ? setCellRef : undefined}
101
- {...props}
102
- className={clsx(
103
- className,
104
- 'relative px-4 first:pl-(--gutter,--spacing(2)) last:pr-(--gutter,--spacing(2))',
105
- !striped && 'border-b border-zinc-950/5 dark:border-white/5',
106
- grid && 'border-l border-l-zinc-950/5 first:border-l-0 dark:border-l-white/5',
107
- dense ? 'py-2.5' : 'py-4',
108
- !bleed && 'sm:first:pl-1 sm:last:pr-1'
109
- )}
110
- >
111
- {href && (
112
- <Link
113
- data-row-link
114
- href={href}
115
- target={target}
116
- aria-label={title}
117
- tabIndex={cellRef?.previousElementSibling === null ? 0 : -1}
118
- className="absolute inset-0 focus:outline-hidden"
119
- />
120
- )}
121
- {children}
122
- </td>
123
- )
124
- }