@proteos/ui 0.56.0 → 0.57.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 (45) hide show
  1. package/dist/{chunk-IKAX76MB.js → chunk-NSE4VW3Z.js} +45 -21
  2. package/dist/chunk-NSE4VW3Z.js.map +1 -0
  3. package/dist/{chunk-MWAXK66H.cjs → chunk-NWGG5WFL.cjs} +45 -21
  4. package/dist/chunk-NWGG5WFL.cjs.map +1 -0
  5. package/dist/index.cjs +336 -351
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +41 -12
  8. package/dist/index.d.ts +41 -12
  9. package/dist/index.js +83 -98
  10. package/dist/index.js.map +1 -1
  11. package/dist/{pdf-view-MH75RVQP.js → pdf-view-RQ2OZYHJ.js} +3 -3
  12. package/dist/{pdf-view-MH75RVQP.js.map → pdf-view-RQ2OZYHJ.js.map} +1 -1
  13. package/dist/{pdf-view-K4MMVHVY.cjs → pdf-view-RRMAUK3L.cjs} +7 -7
  14. package/dist/{pdf-view-K4MMVHVY.cjs.map → pdf-view-RRMAUK3L.cjs.map} +1 -1
  15. package/package.json +2 -2
  16. package/src/components/avatar/avatar.stories.tsx +13 -0
  17. package/src/components/avatar/avatar.tsx +16 -9
  18. package/src/components/badge-multi-select/badge-multi-select.tsx +2 -2
  19. package/src/components/button/button.stories.tsx +202 -97
  20. package/src/components/button/button.test.tsx +40 -7
  21. package/src/components/button/button.tsx +71 -18
  22. package/src/components/combobox/combobox.tsx +2 -2
  23. package/src/components/currency-input/currency-input.tsx +2 -2
  24. package/src/components/date-picker/calendar-internals.tsx +1 -1
  25. package/src/components/date-picker/date-picker.tsx +3 -3
  26. package/src/components/date-time-picker/date-time-picker.tsx +3 -3
  27. package/src/components/icon-picker/icon-picker.tsx +2 -2
  28. package/src/components/image-lightbox/image-lightbox.tsx +2 -2
  29. package/src/components/menu/menu.tsx +2 -2
  30. package/src/components/modal/modal.tsx +4 -4
  31. package/src/components/multi-select/multi-select.tsx +2 -2
  32. package/src/components/popover/popover.tsx +2 -2
  33. package/src/components/record-filter/nested-group.tsx +2 -2
  34. package/src/components/record-filter/record-filter-builder-panel.tsx +11 -23
  35. package/src/components/record-filter/record-filter-chips.tsx +3 -10
  36. package/src/components/segmented-control/segmented-control.stories.tsx +134 -8
  37. package/src/components/segmented-control/segmented-control.test.tsx +81 -8
  38. package/src/components/segmented-control/segmented-control.tsx +38 -19
  39. package/src/components/select/select.tsx +2 -2
  40. package/src/components/time-field/time-field.tsx +1 -1
  41. package/src/components/toast/toast.tsx +2 -2
  42. package/src/components/tooltip/tooltip.tsx +2 -2
  43. package/src/styles.css +58 -0
  44. package/dist/chunk-IKAX76MB.js.map +0 -1
  45. package/dist/chunk-MWAXK66H.cjs.map +0 -1
@@ -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-in entering:fade-in-0 entering:slide-in-from-top-1',
120
- 'exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1',
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-[#f0efe8] data-[focused]:rounded-[3px]',
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-in entering:fade-in-0 entering:slide-in-from-bottom-2 entering:duration-200',
49
- 'exiting:animate-out exiting:fade-out-0 exiting:duration-150',
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-in entering:fade-in-0 entering:slide-in-from-top-1 entering:duration-150',
50
- 'exiting:animate-out exiting:fade-out-0 exiting:duration-100',
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"]}