@proteos/ui 0.56.0 → 0.57.1
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/dist/{chunk-IKAX76MB.js → chunk-NSE4VW3Z.js} +45 -21
- package/dist/chunk-NSE4VW3Z.js.map +1 -0
- package/dist/{chunk-MWAXK66H.cjs → chunk-NWGG5WFL.cjs} +45 -21
- package/dist/chunk-NWGG5WFL.cjs.map +1 -0
- package/dist/index.cjs +346 -352
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -13
- package/dist/index.d.ts +49 -13
- package/dist/index.js +93 -99
- package/dist/index.js.map +1 -1
- package/dist/{pdf-view-MH75RVQP.js → pdf-view-RQ2OZYHJ.js} +3 -3
- package/dist/{pdf-view-MH75RVQP.js.map → pdf-view-RQ2OZYHJ.js.map} +1 -1
- package/dist/{pdf-view-K4MMVHVY.cjs → pdf-view-RRMAUK3L.cjs} +7 -7
- package/dist/{pdf-view-K4MMVHVY.cjs.map → pdf-view-RRMAUK3L.cjs.map} +1 -1
- package/package.json +2 -2
- package/src/components/avatar/avatar.stories.tsx +13 -0
- package/src/components/avatar/avatar.tsx +16 -9
- package/src/components/badge-multi-select/badge-multi-select.tsx +2 -2
- package/src/components/button/button.stories.tsx +202 -97
- package/src/components/button/button.test.tsx +40 -7
- package/src/components/button/button.tsx +71 -18
- package/src/components/combobox/combobox.tsx +2 -2
- package/src/components/currency-input/currency-input.tsx +2 -2
- package/src/components/date-picker/calendar-internals.tsx +1 -1
- package/src/components/date-picker/date-picker.tsx +3 -3
- package/src/components/date-time-picker/date-time-picker.tsx +3 -3
- package/src/components/icon-picker/icon-picker.tsx +2 -2
- package/src/components/image-lightbox/image-lightbox.tsx +2 -2
- package/src/components/menu/menu.tsx +2 -2
- package/src/components/modal/modal.test.tsx +9 -0
- package/src/components/modal/modal.tsx +17 -5
- package/src/components/multi-select/multi-select.tsx +2 -2
- package/src/components/popover/popover.tsx +2 -2
- package/src/components/record-filter/nested-group.tsx +2 -2
- package/src/components/record-filter/record-filter-builder-panel.tsx +11 -23
- package/src/components/record-filter/record-filter-chips.tsx +3 -10
- package/src/components/segmented-control/segmented-control.stories.tsx +134 -8
- package/src/components/segmented-control/segmented-control.test.tsx +81 -8
- package/src/components/segmented-control/segmented-control.tsx +38 -19
- package/src/components/select/select.tsx +2 -2
- package/src/components/time-field/time-field.tsx +1 -1
- package/src/components/toast/toast.tsx +2 -2
- package/src/components/tooltip/tooltip.tsx +2 -2
- package/src/styles.css +58 -0
- package/dist/chunk-IKAX76MB.js.map +0 -1
- package/dist/chunk-MWAXK66H.cjs.map +0 -1
|
@@ -9,11 +9,16 @@ import { tv, type VariantProps } from 'tailwind-variants'
|
|
|
9
9
|
import { cn } from '../../lib/cn'
|
|
10
10
|
|
|
11
11
|
/* =========================================================================
|
|
12
|
-
SegmentedControl — small horizontal exclusive-choice group
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
SegmentedControl — small horizontal exclusive-choice group: a recessed
|
|
13
|
+
`surface-2` track with the selected segment lifted as a white pill. Wraps
|
|
14
|
+
RAC RadioGroup so keyboard nav and focus management are correct (arrow keys
|
|
15
|
+
move between segments, one tab stop). Used for compact toggles like view
|
|
16
|
+
switchers, AND/OR joiners and true/false booleans where a full RadioGroup
|
|
16
17
|
feels heavy.
|
|
18
|
+
|
|
19
|
+
Radii are concentric: 9px (chip) track − 2px padding − 1px hairline = 6px
|
|
20
|
+
(sm) pill. Labels are mode names, so they follow buttons: Inter 500,
|
|
21
|
+
sentence case — not the uppercase mono reserved for eyebrows.
|
|
17
22
|
========================================================================= */
|
|
18
23
|
|
|
19
24
|
export const segmentedControlStyles = tv({
|
|
@@ -22,28 +27,35 @@ export const segmentedControlStyles = tv({
|
|
|
22
27
|
// stretching parent (e.g. a `flex flex-col` card body, whose default
|
|
23
28
|
// align-items:stretch would otherwise pull it to full width). Consumers
|
|
24
29
|
// can still opt into full width by passing `w-full` via className.
|
|
25
|
-
group: 'inline-flex w-fit
|
|
30
|
+
group: 'inline-flex w-fit gap-px p-0.5 rounded-chip bg-surface-2 border border-rule',
|
|
26
31
|
segment: [
|
|
27
|
-
'inline-flex items-center justify-center cursor-pointer',
|
|
28
|
-
'font-
|
|
29
|
-
'transition-[background-color,color] duration-150',
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
'inline-flex items-center justify-center gap-1 cursor-pointer select-none',
|
|
33
|
+
'font-sans font-medium tracking-[-0.005em] rounded-sm outline-none text-ink-3',
|
|
34
|
+
'transition-[background-color,color,box-shadow] duration-150',
|
|
35
|
+
// Unselected: hover/press tint into the track colour. `selected` is
|
|
36
|
+
// declared after `hovered` in styles.css, so the pill wins over these.
|
|
37
|
+
'hovered:text-ink hovered:bg-[color-mix(in_oklab,var(--color-ink)_6%,var(--color-surface-2))]',
|
|
38
|
+
'pressed:bg-[color-mix(in_oklab,var(--color-ink)_10%,var(--color-surface-2))]',
|
|
39
|
+
// Selected: lifted white pill, static.
|
|
40
|
+
'selected:bg-surface selected:text-ink selected:shadow-[var(--shadow-rest)]',
|
|
32
41
|
'data-[focus-visible]:shadow-[var(--shadow-focus)]',
|
|
42
|
+
'selected:data-[focus-visible]:shadow-[var(--shadow-focus),var(--shadow-rest)]',
|
|
33
43
|
'data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed',
|
|
34
44
|
],
|
|
35
45
|
},
|
|
36
46
|
variants: {
|
|
37
47
|
size: {
|
|
38
|
-
sm: { segment: 'px-2 py-0.5 text-[
|
|
39
|
-
md: { segment: 'px-2.5 py-1 text-[
|
|
48
|
+
sm: { segment: 'px-2 py-0.5 text-[11.5px] min-h-[22px]' },
|
|
49
|
+
md: { segment: 'px-2.5 py-1 text-[12.5px] min-h-[26px]' },
|
|
40
50
|
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
// Dense flow-wrapping register (designer inspector): the group becomes a
|
|
52
|
+
// wrapping flex row and every segment grows to share the line.
|
|
53
|
+
wrap: {
|
|
54
|
+
true: { group: 'flex flex-wrap w-auto', segment: 'flex-1 min-w-7 px-1.5' },
|
|
55
|
+
false: {},
|
|
44
56
|
},
|
|
45
57
|
},
|
|
46
|
-
defaultVariants: { size: 'sm',
|
|
58
|
+
defaultVariants: { size: 'sm', wrap: false },
|
|
47
59
|
})
|
|
48
60
|
|
|
49
61
|
export type SegmentedControlVariants = VariantProps<typeof segmentedControlStyles>
|
|
@@ -52,6 +64,8 @@ export type SegmentedControlOption<T extends Key = Key> = {
|
|
|
52
64
|
id: T
|
|
53
65
|
label: ReactNode
|
|
54
66
|
isDisabled?: boolean
|
|
67
|
+
/** Accessible name for icon-only segments. */
|
|
68
|
+
'aria-label'?: string
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
export type SegmentedControlProps<T extends Key = Key> = Omit<
|
|
@@ -59,9 +73,12 @@ export type SegmentedControlProps<T extends Key = Key> = Omit<
|
|
|
59
73
|
'children' | 'value' | 'onChange'
|
|
60
74
|
> & {
|
|
61
75
|
options: ReadonlyArray<SegmentedControlOption<T>>
|
|
62
|
-
|
|
76
|
+
/** `null` renders no selected segment. */
|
|
77
|
+
value: T | null
|
|
63
78
|
onChange: (value: T) => void
|
|
64
79
|
size?: SegmentedControlVariants['size']
|
|
80
|
+
/** Flow-wrap long option lists; segments share the line equally. */
|
|
81
|
+
wrap?: boolean
|
|
65
82
|
/** Focus the selected segment on mount. RAC's RadioGroup doesn't surface
|
|
66
83
|
* `autoFocus` itself — it's a per-Radio prop — so we apply it to the
|
|
67
84
|
* Radio whose value matches `value`. */
|
|
@@ -75,17 +92,18 @@ export function SegmentedControl<T extends Key>({
|
|
|
75
92
|
value,
|
|
76
93
|
onChange,
|
|
77
94
|
size,
|
|
95
|
+
wrap = false,
|
|
78
96
|
autoFocus = false,
|
|
79
97
|
className,
|
|
80
98
|
orientation = 'horizontal',
|
|
81
99
|
...props
|
|
82
100
|
}: SegmentedControlProps<T>) {
|
|
83
|
-
const styles = segmentedControlStyles({ size })
|
|
101
|
+
const styles = segmentedControlStyles({ size, wrap })
|
|
84
102
|
return (
|
|
85
103
|
<AriaRadioGroup
|
|
86
104
|
{...props}
|
|
87
105
|
orientation={orientation}
|
|
88
|
-
value={String(value)}
|
|
106
|
+
value={value === null ? null : String(value)}
|
|
89
107
|
onChange={(next) => onChange(next as T)}
|
|
90
108
|
className={cn(styles.group(), className)}
|
|
91
109
|
>
|
|
@@ -94,6 +112,7 @@ export function SegmentedControl<T extends Key>({
|
|
|
94
112
|
key={String(option.id)}
|
|
95
113
|
value={String(option.id)}
|
|
96
114
|
{...(option.isDisabled ? { isDisabled: true } : {})}
|
|
115
|
+
{...(option['aria-label'] !== undefined ? { 'aria-label': option['aria-label'] } : {})}
|
|
97
116
|
{...(autoFocus && option.id === value ? { autoFocus: true } : {})}
|
|
98
117
|
className={styles.segment()}
|
|
99
118
|
>
|
|
@@ -116,8 +116,8 @@ export function Select<T extends Key>({
|
|
|
116
116
|
'z-[1300]',
|
|
117
117
|
'rounded-md border border-rule bg-surface p-1',
|
|
118
118
|
'shadow-[var(--shadow-raised)]',
|
|
119
|
-
'entering:animate-
|
|
120
|
-
'exiting:animate-
|
|
119
|
+
'entering:animate-enter-slide-down',
|
|
120
|
+
'exiting:animate-exit-slide-up',
|
|
121
121
|
popoverClassName,
|
|
122
122
|
)}
|
|
123
123
|
>
|
|
@@ -78,7 +78,7 @@ export function TimeField<T extends TimeValue = TimeValue>({
|
|
|
78
78
|
'data-[placeholder]:text-ink-4',
|
|
79
79
|
'data-[type=literal]:text-ink-4',
|
|
80
80
|
// segment focus treatment: indigo fill, paper text
|
|
81
|
-
'data-[focused]:bg-accent data-[focused]:text-
|
|
81
|
+
'data-[focused]:bg-accent data-[focused]:text-tile-fg data-[focused]:rounded-[3px]',
|
|
82
82
|
'data-[disabled]:cursor-not-allowed',
|
|
83
83
|
)}
|
|
84
84
|
/>
|
|
@@ -45,8 +45,8 @@ export const toastStyles = tv({
|
|
|
45
45
|
'rounded-lg border border-rule bg-surface shadow-float',
|
|
46
46
|
'px-3.5 py-3 outline-none',
|
|
47
47
|
'focus-visible:shadow-focus',
|
|
48
|
-
'entering:animate-
|
|
49
|
-
'exiting:animate-
|
|
48
|
+
'entering:animate-enter-slide-up',
|
|
49
|
+
'exiting:animate-exit-fade',
|
|
50
50
|
],
|
|
51
51
|
icon: 'size-4 shrink-0 mt-0.5',
|
|
52
52
|
title: 'font-sans text-[13px] font-medium leading-[1.4] text-ink',
|
|
@@ -46,8 +46,8 @@ export function Tooltip({ className, offset = 6, ...props }: TooltipProps) {
|
|
|
46
46
|
'rounded-md border border-rule bg-surface shadow-[var(--shadow-raised)]',
|
|
47
47
|
'px-2.5 py-1.5',
|
|
48
48
|
'font-mono text-[11.5px] text-ink-2',
|
|
49
|
-
'entering:animate-
|
|
50
|
-
'exiting:animate-
|
|
49
|
+
'entering:animate-enter-slide-down',
|
|
50
|
+
'exiting:animate-exit-fade',
|
|
51
51
|
typeof className === 'function' ? className(renderProps) : className,
|
|
52
52
|
)
|
|
53
53
|
}
|
package/src/styles.css
CHANGED
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
to *this* file. */
|
|
15
15
|
@source "./components/**/*.{ts,tsx}";
|
|
16
16
|
|
|
17
|
+
/* React Aria state variants. RAC exposes interaction state as data-* attributes
|
|
18
|
+
(pointer-correct: no sticky :hover on touch; press follows usePress). Same names
|
|
19
|
+
as tailwindcss-react-aria-components, without the dependency. `focus-visible:`
|
|
20
|
+
and `disabled:` stay core. Order matters: `selected` is declared after `hovered`
|
|
21
|
+
so a selected segment's fill wins over its hover fill at equal specificity. */
|
|
22
|
+
@custom-variant hovered (&[data-hovered]);
|
|
23
|
+
@custom-variant pressed (&[data-pressed]);
|
|
24
|
+
@custom-variant selected (&[data-selected]);
|
|
25
|
+
@custom-variant focused (&[data-focused]);
|
|
26
|
+
@custom-variant entering (&[data-entering]);
|
|
27
|
+
@custom-variant exiting (&[data-exiting]);
|
|
28
|
+
|
|
17
29
|
/* ==========================================================
|
|
18
30
|
PROTEOS · INDIGO — design tokens
|
|
19
31
|
Mirrors Proteos Design System v0.1 (spec: revision 2026.04.24).
|
|
@@ -37,6 +49,8 @@
|
|
|
37
49
|
--color-surface: #ffffff;
|
|
38
50
|
--color-surface-2: #f0f0f2;
|
|
39
51
|
--color-surface-3: #e5e5e9;
|
|
52
|
+
/* Deepest recessed step — hover on gray fills (muted buttons). */
|
|
53
|
+
--color-surface-4: #d9d9df;
|
|
40
54
|
|
|
41
55
|
/* Ink — indigo-tinted slate */
|
|
42
56
|
--color-ink: #1a1d2b;
|
|
@@ -124,6 +138,17 @@
|
|
|
124
138
|
status icons. Soft ease, no overshoot (nothing bounces). */
|
|
125
139
|
--animate-status-pop: status-pop var(--duration-slow) var(--ease-out-soft) both;
|
|
126
140
|
|
|
141
|
+
/* Overlay motion — own keyframes. tw-animate-css was never installed, so the
|
|
142
|
+
`animate-in fade-in-0 …` strings compiled to nothing. `both` holds the end
|
|
143
|
+
frame while RAC keeps the element in data-exiting until unmount. */
|
|
144
|
+
--animate-enter-fade: enter-fade var(--duration-fast) ease both;
|
|
145
|
+
--animate-enter-slide-down: enter-slide-down var(--duration-fast) ease both;
|
|
146
|
+
--animate-enter-slide-up: enter-slide-up var(--duration-base) ease both;
|
|
147
|
+
--animate-enter-zoom: enter-zoom var(--duration-fast) ease both;
|
|
148
|
+
--animate-exit-fade: exit-fade 100ms ease both;
|
|
149
|
+
--animate-exit-slide-up: exit-slide-up 100ms ease both;
|
|
150
|
+
--animate-exit-zoom: exit-zoom 100ms ease both;
|
|
151
|
+
|
|
127
152
|
}
|
|
128
153
|
|
|
129
154
|
@keyframes indeterminate-progress {
|
|
@@ -149,6 +174,37 @@
|
|
|
149
174
|
}
|
|
150
175
|
}
|
|
151
176
|
|
|
177
|
+
@keyframes enter-fade {
|
|
178
|
+
from { opacity: 0; }
|
|
179
|
+
}
|
|
180
|
+
@keyframes enter-slide-down {
|
|
181
|
+
from { opacity: 0; transform: translateY(-4px); }
|
|
182
|
+
}
|
|
183
|
+
@keyframes enter-slide-up {
|
|
184
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
185
|
+
}
|
|
186
|
+
@keyframes enter-zoom {
|
|
187
|
+
from { opacity: 0; transform: scale(0.95); }
|
|
188
|
+
}
|
|
189
|
+
@keyframes exit-fade {
|
|
190
|
+
to { opacity: 0; }
|
|
191
|
+
}
|
|
192
|
+
@keyframes exit-slide-up {
|
|
193
|
+
to { opacity: 0; transform: translateY(-4px); }
|
|
194
|
+
}
|
|
195
|
+
@keyframes exit-zoom {
|
|
196
|
+
to { opacity: 0; transform: scale(0.95); }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@media (prefers-reduced-motion: reduce) {
|
|
200
|
+
[data-entering],
|
|
201
|
+
[data-exiting],
|
|
202
|
+
[class*="animate-enter-"],
|
|
203
|
+
[class*="animate-exit-"] {
|
|
204
|
+
animation: none;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
152
208
|
/* Raw variables (non-color) for direct component consumption.
|
|
153
209
|
Tailwind v4 mirrors @theme into :root for colors/radii/shadows, but we
|
|
154
210
|
also expose spacing tokens here for components that need raw var() access. */
|
|
@@ -201,6 +257,7 @@
|
|
|
201
257
|
--color-surface: #f2f0ea;
|
|
202
258
|
--color-surface-2: #e7e4db;
|
|
203
259
|
--color-surface-3: #dcd8cc;
|
|
260
|
+
--color-surface-4: #d0ccbf;
|
|
204
261
|
|
|
205
262
|
--color-ink: #1a1d2b;
|
|
206
263
|
--color-ink-2: #353a4b;
|
|
@@ -240,6 +297,7 @@
|
|
|
240
297
|
--color-surface: #191c24;
|
|
241
298
|
--color-surface-2: #222633;
|
|
242
299
|
--color-surface-3: #2c3140;
|
|
300
|
+
--color-surface-4: #363b4c;
|
|
243
301
|
|
|
244
302
|
--color-ink: #e9eaf0;
|
|
245
303
|
--color-ink-2: #c5c8d4;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cn.ts","../src/components/button/button.tsx","../src/components/skeleton/skeleton.tsx"],"names":["AriaButton","tv","jsx"],"mappings":"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","file":"chunk-IKAX76MB.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { Button as AriaButton, type ButtonProps as AriaButtonProps } from 'react-aria-components'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\nexport const buttonStyles = tv({\n base: [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap cursor-pointer',\n 'font-mono tracking-[-0.005em] border border-transparent',\n 'transition-[background-color,color,border-color,box-shadow,transform] duration-150',\n 'outline-none pressed:translate-y-px',\n 'focus-visible:shadow-[var(--shadow-focus)]',\n 'disabled:opacity-45 disabled:cursor-not-allowed disabled:pointer-events-none',\n ],\n variants: {\n variant: {\n primary: ['bg-ink text-surface border-ink', 'hover:bg-accent-ink hover:border-accent-ink'],\n // Hover uses accent-2 — the token DESIGN.md reserves for \"hover on\n // accent\". accent-ink is a text-on-tinted-surface color and flips\n // light in dark mode, so it can't double as a hover fill here.\n accent: [\n 'bg-accent text-[#f0efe8] border-accent',\n 'hover:bg-accent-2 hover:border-accent-2',\n ],\n secondary: ['bg-transparent text-ink border-ink', 'hover:bg-ink hover:text-surface'],\n ghost: [\n 'bg-bg text-ink-2 border-rule-strong',\n 'hover:bg-surface-2 hover:text-ink hover:border-ink-4',\n ],\n // Transparent at rest, paper-fill on hover. The toolbar / sidebar\n // register — pairs with `size=\"icon-md\"` for top-bar icon buttons.\n subtle: ['bg-transparent text-ink-3 border-transparent', 'hover:bg-surface-2 hover:text-ink'],\n link: [\n 'bg-transparent text-ink-2 border-transparent',\n 'px-0.5 border-b border-b-ink-4',\n 'hover:text-ink hover:border-b-ink',\n ],\n },\n size: {\n sm: 'text-xs px-3 py-1.5 [&_svg]:size-3',\n md: 'text-[13px] px-4 py-[9px] [&_svg]:size-3',\n lg: 'text-sm px-[22px] py-3 [&_svg]:size-3.5',\n // Square dimensions for icon-only buttons. Requires an `aria-label`.\n 'icon-sm': 'size-7 p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-[34px] p-0 [&_svg]:size-4',\n 'icon-lg': 'size-[42px] p-0 [&_svg]:size-[18px]',\n },\n // Corner shape. Default is rounded (soft 10px radius — the standard\n // Proteos button), `pill` is the fully-rounded legacy treatment.\n // The `link` variant overrides both to a flat underline.\n shape: {\n rounded: 'rounded-md',\n pill: 'rounded-pill',\n },\n },\n compoundVariants: [\n { variant: 'link', size: 'sm', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'md', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'lg', class: 'px-0.5 py-0' },\n // Link never takes a corner radius — it's an underline, not a box.\n { variant: 'link', shape: 'rounded', class: 'rounded-none' },\n { variant: 'link', shape: 'pill', class: 'rounded-none' },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n shape: 'rounded',\n },\n})\n\nexport type ButtonVariants = VariantProps<typeof buttonStyles>\nexport type ButtonProps = AriaButtonProps & ButtonVariants\n\nexport function Button({ variant, size, shape, className, ...props }: ButtonProps) {\n return (\n <AriaButton\n {...props}\n className={(renderProps) =>\n cn(\n buttonStyles({ variant, size, shape }),\n typeof className === 'function' ? className(renderProps) : className,\n )\n }\n />\n )\n}\n","import type { HTMLAttributes } from 'react'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\n/* =========================================================================\n Skeleton — content placeholder for loading states.\n Purely presentational, so it doesn't wrap a React Aria primitive (RAC has\n no Skeleton — interactive primitives only). Accessibility lives in props:\n - decorative skeletons get `aria-hidden` so screen readers ignore them\n - skeletons that *announce* the loading state should be wrapped in a\n `role=\"status\"` region by the consumer (e.g. AppLayoutSkeleton).\n ========================================================================= */\n\nexport const skeletonStyles = tv({\n base: ['animate-pulse', 'bg-surface-3'],\n variants: {\n shape: {\n rect: 'rounded-md',\n circle: 'rounded-full',\n // `text` matches a typical line of body text — width is up to the\n // consumer; the rounded-sm + height keep proportions sensible.\n text: 'h-4 w-full rounded-sm',\n },\n },\n defaultVariants: { shape: 'rect' },\n})\n\nexport type SkeletonVariants = VariantProps<typeof skeletonStyles>\nexport type SkeletonProps = HTMLAttributes<HTMLDivElement> & SkeletonVariants\n\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return (\n <div\n // Decorative by default. Consumers that want screen readers to announce\n // the loading state should wrap a Skeleton group in `role=\"status\"`\n // and pass `aria-hidden={false}` here, or just rely on the wrapper.\n aria-hidden=\"true\"\n {...props}\n className={cn(skeletonStyles({ shape }), className)}\n />\n )\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cn.ts","../src/components/button/button.tsx","../src/components/skeleton/skeleton.tsx"],"names":["twMerge","clsx","tv","jsx","AriaButton"],"mappings":"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","file":"chunk-MWAXK66H.cjs","sourcesContent":["import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { Button as AriaButton, type ButtonProps as AriaButtonProps } from 'react-aria-components'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\nexport const buttonStyles = tv({\n base: [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap cursor-pointer',\n 'font-mono tracking-[-0.005em] border border-transparent',\n 'transition-[background-color,color,border-color,box-shadow,transform] duration-150',\n 'outline-none pressed:translate-y-px',\n 'focus-visible:shadow-[var(--shadow-focus)]',\n 'disabled:opacity-45 disabled:cursor-not-allowed disabled:pointer-events-none',\n ],\n variants: {\n variant: {\n primary: ['bg-ink text-surface border-ink', 'hover:bg-accent-ink hover:border-accent-ink'],\n // Hover uses accent-2 — the token DESIGN.md reserves for \"hover on\n // accent\". accent-ink is a text-on-tinted-surface color and flips\n // light in dark mode, so it can't double as a hover fill here.\n accent: [\n 'bg-accent text-[#f0efe8] border-accent',\n 'hover:bg-accent-2 hover:border-accent-2',\n ],\n secondary: ['bg-transparent text-ink border-ink', 'hover:bg-ink hover:text-surface'],\n ghost: [\n 'bg-bg text-ink-2 border-rule-strong',\n 'hover:bg-surface-2 hover:text-ink hover:border-ink-4',\n ],\n // Transparent at rest, paper-fill on hover. The toolbar / sidebar\n // register — pairs with `size=\"icon-md\"` for top-bar icon buttons.\n subtle: ['bg-transparent text-ink-3 border-transparent', 'hover:bg-surface-2 hover:text-ink'],\n link: [\n 'bg-transparent text-ink-2 border-transparent',\n 'px-0.5 border-b border-b-ink-4',\n 'hover:text-ink hover:border-b-ink',\n ],\n },\n size: {\n sm: 'text-xs px-3 py-1.5 [&_svg]:size-3',\n md: 'text-[13px] px-4 py-[9px] [&_svg]:size-3',\n lg: 'text-sm px-[22px] py-3 [&_svg]:size-3.5',\n // Square dimensions for icon-only buttons. Requires an `aria-label`.\n 'icon-sm': 'size-7 p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-[34px] p-0 [&_svg]:size-4',\n 'icon-lg': 'size-[42px] p-0 [&_svg]:size-[18px]',\n },\n // Corner shape. Default is rounded (soft 10px radius — the standard\n // Proteos button), `pill` is the fully-rounded legacy treatment.\n // The `link` variant overrides both to a flat underline.\n shape: {\n rounded: 'rounded-md',\n pill: 'rounded-pill',\n },\n },\n compoundVariants: [\n { variant: 'link', size: 'sm', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'md', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'lg', class: 'px-0.5 py-0' },\n // Link never takes a corner radius — it's an underline, not a box.\n { variant: 'link', shape: 'rounded', class: 'rounded-none' },\n { variant: 'link', shape: 'pill', class: 'rounded-none' },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n shape: 'rounded',\n },\n})\n\nexport type ButtonVariants = VariantProps<typeof buttonStyles>\nexport type ButtonProps = AriaButtonProps & ButtonVariants\n\nexport function Button({ variant, size, shape, className, ...props }: ButtonProps) {\n return (\n <AriaButton\n {...props}\n className={(renderProps) =>\n cn(\n buttonStyles({ variant, size, shape }),\n typeof className === 'function' ? className(renderProps) : className,\n )\n }\n />\n )\n}\n","import type { HTMLAttributes } from 'react'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\n/* =========================================================================\n Skeleton — content placeholder for loading states.\n Purely presentational, so it doesn't wrap a React Aria primitive (RAC has\n no Skeleton — interactive primitives only). Accessibility lives in props:\n - decorative skeletons get `aria-hidden` so screen readers ignore them\n - skeletons that *announce* the loading state should be wrapped in a\n `role=\"status\"` region by the consumer (e.g. AppLayoutSkeleton).\n ========================================================================= */\n\nexport const skeletonStyles = tv({\n base: ['animate-pulse', 'bg-surface-3'],\n variants: {\n shape: {\n rect: 'rounded-md',\n circle: 'rounded-full',\n // `text` matches a typical line of body text — width is up to the\n // consumer; the rounded-sm + height keep proportions sensible.\n text: 'h-4 w-full rounded-sm',\n },\n },\n defaultVariants: { shape: 'rect' },\n})\n\nexport type SkeletonVariants = VariantProps<typeof skeletonStyles>\nexport type SkeletonProps = HTMLAttributes<HTMLDivElement> & SkeletonVariants\n\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return (\n <div\n // Decorative by default. Consumers that want screen readers to announce\n // the loading state should wrap a Skeleton group in `role=\"status\"`\n // and pass `aria-hidden={false}` here, or just rely on the wrapper.\n aria-hidden=\"true\"\n {...props}\n className={cn(skeletonStyles({ shape }), className)}\n />\n )\n}\n"]}
|